📄 s3.c
字号:
if (s3_chiptype >= S3_864) { if (modeinfo->bitsPerPixel >= 8) { /* Enable linear addressing. */ moderegs[S3_CR58] |= 0x10; /* Set window size to 64K. */ moderegs[S3_CR58] &= ~0x03; /* Assume CR59/5A are correctly set up for 0xA0000. */ /* Set CR6A linear bank to zero. */ moderegs[S3_CR6A] &= ~0x3F; /* use alternate __svgalib_setpage() function */ __svgalib_s3_driverspecs.__svgalib_setpage = s3_setpage864; } else { /* doesn't work for 4bpp. */ __svgalib_s3_driverspecs.__svgalib_setpage = s3_setpage; } }#endif moderegs[S3_CR59] = 0; moderegs[S3_CR5A] = 0x0A; /* Extended CRTC timing. */ moderegs[S3_CR5E] = (((modetiming->CrtcVTotal - 2) & 0x400) >> 10) | (((modetiming->CrtcVDisplay - 1) & 0x400) >> 9) | (((modetiming->CrtcVSyncStart) & 0x400) >> 8) | (((modetiming->CrtcVSyncStart) & 0x400) >> 6) | 0x40; { int i, j; i = ((((modetiming->CrtcHTotal >> 3) - 5) & 0x100) >> 8) | ((((modetiming->CrtcHDisplay >> 3) - 1) & 0x100) >> 7) | ((((modetiming->CrtcHSyncStart >> 3) - 1) & 0x100) >> 6) | ((modetiming->CrtcHSyncStart & 0x800) >> 7); j = ((moderegs[VGA_CR0] + ((i & 0x01) << 8) + moderegs[VGA_CR4] + ((i & 0x10) << 4) + 1) / 2); moderegs[S3_CR3B] = j & 0xFF; i |= (j & 0x100) >> 2; /* Interlace mode frame offset. */ moderegs[S3_CR3C] = (moderegs[VGA_CR0] + ((i & 0x01) << 8)) / 2; moderegs[S3_CR5D] &= ~0x57; moderegs[S3_CR5D] |= i; } { int i;#if 0 /* This seems wrong. Why doesn't XF86_S3 have problems? */ if (s3_chiptype == S3_864 && s3_memory > 1024) i = modetiming->HDisplay * modeinfo->bytesPerPixel / 8 + 1; /* else */#endif if (modeinfo->bitsPerPixel < 8) i = modetiming->HDisplay / 4 + 1; else i = modetiming->HDisplay * modeinfo->bytesPerPixel / 4 + 1; moderegs[S3_CR61] = (i >> 8) | 0x80; moderegs[S3_CR62] = i & 0xFF; } } /* 801+ */ if (modetiming->flags & INTERLACED) moderegs[S3_CR42] |= 0x20; /* * Clock select works as follows: * Clocks 0 and 1 (VGA 25 and 28 MHz) can be selected via the * two VGA MiscOutput clock select bits. * If 0x3 is written to these bits, the selected clock index * is taken from the S3 clock select register at CR42. Clock * indices 0 and 1 should correspond to the VGA ones above, * and 3 is often 0 MHz, followed by extended clocks for a * total of mostly 16. */ if (modetiming->flags & USEPROGRCLOCK) moderegs[VGA_MISCOUTPUT] |= 0x0C; /* External clock select. */ else if (modetiming->selectedClockNo < 2) { /* Program clock select bits 0 and 1. */ moderegs[VGA_MISCOUTPUT] &= ~0x0C; moderegs[VGA_MISCOUTPUT] |= (modetiming->selectedClockNo & 3) << 2; } else if (modetiming->selectedClockNo >= 2) { moderegs[VGA_MISCOUTPUT] |= 0x0C; /* Program S3 clock select bits. */ moderegs[S3_CR42] &= ~0x1F; moderegs[S3_CR42] |= modetiming->selectedClockNo; } if (s3_chiptype == S3_TRIO64 || s3_chiptype == S3_765) { moderegs[S3_CR33] &= ~0x08; if (modeinfo->bitsPerPixel == 16) moderegs[S3_CR33] |= 0x08; /* * The rest of the DAC/clocking is setup by the * Trio64 code in the RAMDAC interface (ramdac.c). */ } if (dac_used->id != NORMAL_DAC) { int colormode; colormode = __svgalib_colorbits_to_colormode(modeinfo->bitsPerPixel, modeinfo->colorBits); dac_used->initializeState(&moderegs[S3_DAC_OFFSET], modeinfo->bitsPerPixel, colormode, modetiming->pixelClock); if (dac_used->id == ATT20C490) { int pixmux, invert_vclk, blank_delay; pixmux = 0; invert_vclk = 0; blank_delay = 2; if (colormode == CLUT8_6 && modetiming->pixelClock >= 67500) { pixmux = 0x00; invert_vclk = 1; } else if (colormode == CLUT8_8) pixmux = 0x02; else if (colormode == RGB16_555) pixmux = 0xa0; else if (colormode == RGB16_565) pixmux = 0xc0; else if (colormode == RGB24_888_B) pixmux = 0xe0; moderegs[S3_CR67] = pixmux | invert_vclk; moderegs[S3_CR6D] = blank_delay; } if (dac_used->id == S3_SDAC) { int pixmux, invert_vclk, blank_delay; pixmux = 0; invert_vclk = 0; blank_delay = 0; if (colormode == CLUT8_6 && modetiming->pixelClock >= 67500) {#ifdef SDAC_8BPP_PIXMUX /* x64 8bpp pixel multiplexing? */ pixmux = 0x10; if (s3_chiptype != S3_866 && s3_chiptype != S3_868) invert_vclk = 1; blank_delay = 2;#endif } else if (colormode == RGB16_555) { pixmux = 0x30; blank_delay = 2; } else if (colormode == RGB16_565) { pixmux = 0x50; blank_delay = 2; } else if (colormode == RGB24_888_B) { /* XXXX 868/968 only */ pixmux = 0x90; blank_delay = 2; } else if (colormode == RGB32_888_B) { pixmux = 0x70; blank_delay = 2; } moderegs[S3_CR67] = pixmux | invert_vclk; moderegs[S3_CR6D] = blank_delay; /* Clock select. */ moderegs[S3_CR42] &= ~0x0F; moderegs[S3_CR42] |= 0x02; } if (dac_used->id == IBMRGB52x) { unsigned char pixmux, blank_delay, tmp; tmp = 0; pixmux = 0x11; blank_delay = 0; if (modeinfo->bitsPerPixel < 8 || colormode == RGB32_888_B) pixmux = 0x00; moderegs[S3_CR58] |= 0x40; moderegs[S3_CR65] = 0; moderegs[S3_CR66] &= 0xf8; moderegs[S3_CR66] |= tmp;#ifdef PIXEL_MULTIPLEXING moderegs[S3_CR67] = pixmux;#endif moderegs[S3_CR6D] = blank_delay; /* Clock select. */ moderegs[S3_CR42] &= ~0x0F; moderegs[S3_CR42] |= 0x02; } } if (clk_used == &__svgalib_I2061A_clockchip_methods && (modetiming->flags & USEPROGRCLOCK)) { /* Clock select. */ moderegs[S3_CR42] &= ~0x0F; moderegs[S3_CR42] |= 0x02; } /* update the 8514 regs */ memcpy(moderegs + S3_8514_OFFSET, s3_8514regs, S3_8514_COUNT * 2);}/* Set a mode */static int s3_setmode(int mode, int prv_mode){ ModeInfo *modeinfo; ModeTiming *modetiming; unsigned char moderegs[S3_TOTAL_REGS]; int res; if (mode < G640x480x256 || mode == G720x348x2) { /* Let the standard VGA driver set standard VGA modes. */ res = __svgalib_vga_driverspecs.setmode(mode, prv_mode); if (res == 0 && s3_chiptype <= S3_928) { /* * ARI: Turn off virtual size of 1024 - this fixes all problems * with standard modes, including 320x200x256. * * SL: Is this for 928 only? Doesn't matter for 805. */ s3_unlock(); __svgalib_outCR(0x34, __svgalib_inCR(0x34) & ~0x10); s3_lock(); } return res; } if (!s3_modeavailable(mode)) return 1; modeinfo = __svgalib_createModeInfoStructureForSvgalibMode(mode); modetiming = malloc(sizeof(ModeTiming)); if (__svgalib_getmodetiming(modetiming, modeinfo, cardspecs)) { free(modetiming); free(modeinfo); return 1; } /* Adjust the display width. */ modeinfo->lineWidth = s3_adjlinewidth(modeinfo->lineWidth); CI.xbytes = modeinfo->lineWidth; s3_initializemode(moderegs, modetiming, modeinfo); free(modeinfo); free(modetiming); __svgalib_setregs(moderegs); /* Set standard regs. */ s3_setregs(moderegs, mode); /* Set extended regs. */ return 0;}/* Indentify chipset; return non-zero if detected *//* Some port I/O functions: */static unsigned char rdinx(int port, unsigned char index){ outb(port, index); return inb(port + 1);}static void wrinx(int port, unsigned char index, unsigned char val){ outb(port, index); outb(port + 1, val);}/* * Returns true iff the bits in 'mask' of register 'port', index 'index' * are read/write. */static int testinx2(int port, unsigned char index, unsigned char mask){ unsigned char old, new1, new2; old = rdinx(port, index); wrinx(port, index, (old & ~mask)); new1 = rdinx(port, index) & mask; wrinx(port, index, (old | mask)); new2 = rdinx(port, index) & mask; wrinx(port, index, old); return (new1 == 0) && (new2 == mask);}static int s3_test(void){ int vgaIOBase, vgaCRIndex, vgaCRReg; vgaIOBase = (inb(0x3CC) & 0x01) ? 0x3D0 : 0x3B0; vgaCRIndex = vgaIOBase + 4; vgaCRReg = vgaIOBase + 5; outb(vgaCRIndex, 0x11); /* for register CR11, (Vertical Retrace End) */ outb(vgaCRReg, 0x00); /* set to 0 */ 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)) return 0; 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)) return 0; if (s3_init(0, 0, 0)) /* type not OK */ return 0; { unsigned long buf[16]; if (s3_pci = !(__svgalib_pci_find_vendor_vga(VENDOR_S3, buf))) s3_pci_linearbase = buf[4] & 0xFF800000; } return 1;}/* * Bank switching function - set 64K bank number * * XXXX locking and unlocking might hurt performance but is safer. */static void s3_setpage(int page){#ifdef S3_16_COLORS /* * XXXX adjust the parameter for 4bpp (1bpp is ignored). Shouldn't * need this, but either me or the drawing functions are making bad * assumptions about 4bpp. */ if (infotable[CM].bytesperpixel == 0) page *= 4;#endif#ifdef S3_KLUDGE_PAGE_MODE /* adjust to use 256K pages */ if (CM == G320x200x256) page *= 4;#endif s3_unlock(); outb(0x3d4, 0x35); outb(0x3d5, (inb(0x3d5) & 0xF0) | (page & 0x0F)); if (s3_chiptype >= S3_801) { outb(0x3d4, 0x51); outb(0x3d5, (inb(0x3d5) & ~0x0C) | ((page & 0x30) >> 2)); } inb(0x3d5); /* ARI: Ferraro says: required for first generation 911 only */ s3_lock();}/* * Bank switching function - set 64K bank number for 864+ * (not for 4bpp) * * XXXX locking and unlocking might hurt performance * (864 shouldn't need it). */#ifdef S3_LINEAR_MODE_BANKING_864static void s3_setpage864(int page){ s3_unlock(); /* "Linear" mode banking. */ outb(0x3d4, 0x6A); outb(0x3d5, (inb(0x3d5) & ~0x3F) | page); s3_lock();}#endif/* * Set display start address (not for 16 color modes). * * This works up to 4Mb (should be able to go higher). * * XXXX locking and unlocking might hurt performance but is safer. */static void s3_setdisplaystart(int address){#ifdef S3_KLUDGE_PAGE_MODE /* adjust to use 256K pages */ if (CM == G320x200x256) address *= 4;#endif s3_unlock(); outw(0x3d4, 0x0d | ((address << 6) & 0xff00)); /* sa2-sa9 */ outw(0x3d4, 0x0c | ((address >> 2) & 0xff00)); /* sa10-sa17 */ inb(0x3da); /* set ATC to addressing mode */ outb(0x3c0, 0x13 + 0x20); /* select ATC reg 0x13 */ outb(0x3c0, (inb(0x3c1) & 0xf0) | ((address & 3) << 1)); /* write sa0-1 to bits 1-2 */ outb(0x3d4, 0x31); outb(0x3d5, (inb(0x3d5) & ~0x30) | ((address & 0xc0000) >> 14)); if (s3_chiptype >= S3_801) { outb(0x3d4, 0x51); outb(0x3d5, (inb(0x3d5) & ~0x03) | ((address & 0x300000) >> 20)); } s3_lock();}/* * Set logical scanline length (Multiples of 8 to 8184). * CR43.2 should be 0 for this. */static void s3_setlogicalwidth(int width){ __svgalib_outCR(0x13, (width >> 3)); /* lw3-lw11 */ __svgalib_outCR(0x51, (width & 0x300) >> 4); /* lw12-lw13 */}#ifdef S3_LINEAR_SUPPORTstatic void s3_setlinear(unsigned int addr){ /* printf("s3_setlinear(0x%x) called\n", addr); */ s3_unlock(); outb(0x3d4, 0x58); if (addr) { int m; switch (s3_memory) { case 1024: m = 1; break; case 2048: m = 2; break; default: if (s3_memory > 2048) m = 3; else { printf("%s: mapping 1MB, but you've only got %dK!\n", __FUNCTION__); m = 1; } } outb(0x3d5, inb(0x3d5) | 0x10 | m); /* enable linear mode */ __svgalib_outCR(0x59, (addr >> 8)); __svgalib_outCR(0x5A, (addr) & 0xFF); } else { outb(0x3d5, inb(0x3d5) & ~0x13); /* disable linear mode */ __svgalib_outCR(0x59, 0x00); __svgalib_outCR(0x5A, 0x0A); } s3_lock();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -