📄 s3.c
字号:
(((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); if ((modetiming->CrtcHSyncEnd >> 3) - (modetiming->CrtcHSyncStart >> 3) > 64) i |= 0x08; if ((modetiming->CrtcHSyncEnd >> 3) - (modetiming->CrtcHSyncStart >> 3) > 32) i |= 0x20; j = ((moderegs[VGA_CR0] + ((i & 0x01) << 8) + moderegs[VGA_CR4] + ((i & 0x10) << 4) + 1) / 2); if (j - (moderegs[VGA_CR4] + ((i & 0x10) << 4)) < 4) { if (moderegs[VGA_CR4] + ((i & 0x10) << 4) + 4 <= moderegs[VGA_CR0] + ((i & 0x01) << 8)) j = moderegs[VGA_CR4] + ((i & 0x10) << 4) + 4; else j = moderegs[VGA_CR0] + ((i & 0x01) << 8) + 1; } 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] = (moderegs[S3_CR5D] & 0x80) | i; } { int i; 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; } }#ifdef S3_LINEAR_SUPPORT s3_cr58 = moderegs[S3_CR58]; s3_cr40 = moderegs[S3_CR40]; s3_cr54 = moderegs[S3_CR54];#endif 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) { /* * 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. * * MZ: Affects 765 as well, so I assume it is good for all chipsets. */ 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; 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(CRT_IC, 0x35); outb(CRT_DC, (inb(CRT_DC) & 0xF0) | (page & 0x0F)); if (s3_chiptype >= S3_801) { outb(CRT_IC, 0x51); outb(CRT_DC, (inb(CRT_DC) & ~0x0C) | ((page & 0x30) >> 2)); } inb(CRT_DC); /* 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(CRT_IC, 0x6A); outb(CRT_DC, (inb(CRT_DC) & ~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(CRT_IC, 0x0d | ((address << 6) & 0xff00)); /* sa2-sa9 */ outw(CRT_IC, 0x0c | ((address >> 2) & 0xff00)); /* sa10-sa17 */ inb(0x3da); /* set ATC to addressing mode */ outb(ATT_IW, 0x13 + 0x20); /* select ATC reg 0x13 */ outb(ATT_IW, (inb(ATT_R) & 0xf0) | ((address & 3) << 1)); /* write sa0-1 to bits 1-2 */ outb(CRT_IC, 0x31); outb(CRT_DC, (inb(CRT_DC) & ~0x30) | ((address & 0xc0000) >> 14)); if (s3_chiptype >= S3_801) { outb(CRT_IC, 0x51); outb(CRT_DC, (inb(CRT_DC) & ~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_linear_enable(void){ s3_unlock(); if (s3_chiptype > S3_924) { int i; outb (CRT_IC, 0x40); i = (s3_cr40 & 0xf6) | 0x0a; outb (CRT_DC, (unsigned char) i); outb (CRT_IC, 0x58); outb (CRT_DC, s3_linear_opt | s3_cr58); if (s3_chiptype > S3_928) { outb (CRT_IC, 0x54); outb (CRT_DC, (s3_cr54 + 0x07)); } } s3_lock();}static void s3_linear_disable(void){ s3_unlock(); if (s3_chiptype > S3_924) { if (s3_chiptype > S3_928) { outb (CRT_IC, 0x54); outb (CRT_DC, s3_cr54); } outb (CRT_IC, 0x58); outb (CRT_DC, s3_cr58); outb (CRT_IC, 0x40); outb (CRT_DC, s3_cr40); } s3_lock();}/* Set linear addressing mode */static int s3_linear(int op, int param){ if (op == LINEAR_QUERY_BASE) return s3_linear_base; if (op == LINEAR_QUERY_GRANULARITY) { switch (s3_memory) { case 4096: case 2048: case 1024: return s3_memory * 1024; default: return 1024 * 1024; } } else if (op == LINEAR_QUERY_RANGE) return 256; else if (op == LINEAR_ENABLE) { s3_setpage(0); s3_linear_enable(); s3_linear_addr = param; return 0; } else if (op == LINEAR_DISABLE) { s3_setpage(0); s3_linear_disable(); s3_linear_addr = 0; return 0; } else return -1;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -