📄 savage.c
字号:
/*Savage chipset driver Written by Matan Ziv-Av (matan@svgalib.org)Based on XFree 3.3.6 driver by S. Marineau and Tim Roberts.*/#include <stdlib.h>#include <stdio.h> #include <string.h>#include <unistd.h>#include <sys/mman.h>#include "vga.h"#include "libvga.h"#include "driver.h"#include "timing.h"#include "vgaregs.h"#include "interface.h"#include "accel.h"#include "vgapci.h"#define SAVAGEREG_SAVE(i) (VGA_TOTAL_REGS+i)#define SAVAGE_TOTAL_REGS (VGA_TOTAL_REGS + 64)typedef struct { unsigned char SR8, SR10, SR11, SR12, SR13, SR15, SR18, SR29; /* SR9-SR1C, ext seq. */ /*unsigned char SR54, SR55, SR56, SR57;*/ unsigned char Clock;// unsigned char s3DacRegs[0x101]; unsigned char CR31, CR33, CR34, CR36, CR3A, CR3B, CR3C; unsigned char CR40, CR42, CR43, CR45; unsigned char CR50, CR51, CR53, CR58, CR5B, CR5D, CR5E; unsigned char CR65, CR66, CR67, CR68, CR69, CR6F; /* Video attrib. */ unsigned char CR86, CR88; unsigned char CR90, CR91, CRB0; unsigned int MMPR0, MMPR1, MMPR2, MMPR3; /* MIU regs */} vgaS3VRec, *vgaS3VPtr;#define BSWAP(x) x = (x>>24) | ((x>>8) & 0xff00)| ((x<<8) & 0xff0000)|(x<<24)static int savage_init(int, int, int);static void savage_unlock(void);static void savage_lock(void);void __svgalib_savageaccel_init(AccelSpecs * accelspecs, int bpp, int width_in_pixels);enum { UNKNOWN, SAVAGE3D, SAVAGEMX, SAVAGE4, SAVAGEPRO, SAVAGE2000 };static int savage_memory, savage_chipset;static int savage_is_linear, savage_linear_base;static CardSpecs *cardspecs;static void savage_setpage(int page){ __svgalib_outcrtc(0x6a, page);}static int __svgalib_savage_inlinearmode(void){return savage_is_linear;}/* Fill in chipset specific mode information */static void savage_getmodeinfo(int mode, vga_modeinfo *modeinfo){ if(modeinfo->colors==16)return; modeinfo->maxpixels = savage_memory*1024/modeinfo->bytesperpixel; modeinfo->maxlogicalwidth = 4088; modeinfo->startaddressrange = savage_memory * 1024 - 1; modeinfo->haveblit = 0; modeinfo->flags &= ~HAVE_RWPAGE; if (modeinfo->bytesperpixel >= 1) { if(savage_linear_base)modeinfo->flags |= CAPABLE_LINEAR; if (__svgalib_savage_inlinearmode()) modeinfo->flags |= IS_LINEAR; }}/* Read and save chipset-specific registers */static int savage_saveregs(unsigned char regs[]){ unsigned char cr3a, cr66; vgaS3VPtr save = (vgaS3VPtr)(regs+VGA_TOTAL_REGS); savage_unlock(); cr66 = __svgalib_incrtc(0x66); __svgalib_outcrtc(0x66, cr66 | 0x80); cr3a = __svgalib_incrtc(0x3a); __svgalib_outcrtc(0x3a, cr3a | 0x80); cr66 = __svgalib_incrtc(0x66); __svgalib_outcrtc(0x66, cr66 | 0x80); cr3a = __svgalib_incrtc(0x3a); __svgalib_outcrtc(0x3a, cr3a | 0x80);#if 0 save = (vgaS3VPtr)vgaHWSave((vgaHWPtr)save, sizeof(vgaS3VRec));#endif __svgalib_outcrtc(0x66, cr66); __svgalib_outcrtc(0x3a, cr3a); __svgalib_outcrtc(0x66, cr66); __svgalib_outcrtc(0x3a, cr3a); /* First unlock extended sequencer regs */ save->SR8 = __svgalib_inseq(0x08); __svgalib_outseq(0x08, 0x06); /* Now we save all the s3 extended regs we need */ save->CR31 = __svgalib_incrtc(0x31); save->CR34 = __svgalib_incrtc(0x34); save->CR36 = __svgalib_incrtc(0x36); save->CR3A = __svgalib_incrtc(0x3a); save->CR40 = __svgalib_incrtc(0x40); save->CR42 = __svgalib_incrtc(0x42); save->CR45 = __svgalib_incrtc(0x45); save->CR50 = __svgalib_incrtc(0x50); save->CR51 = __svgalib_incrtc(0x51); save->CR53 = __svgalib_incrtc(0x53); save->CR58 = __svgalib_incrtc(0x58); save->CR66 = __svgalib_incrtc(0x66); save->CR67 = __svgalib_incrtc(0x67); save->CR68 = __svgalib_incrtc(0x68); save->CR69 = __svgalib_incrtc(0x69); save->CR6F = __svgalib_incrtc(0x6f); save->CR33 = __svgalib_incrtc(0x33); save->CR86 = __svgalib_incrtc(0x86); save->CR88 = __svgalib_incrtc(0x88); save->CR90 = __svgalib_incrtc(0x90); save->CR91 = __svgalib_incrtc(0x91); save->CRB0 = __svgalib_incrtc(0xb0) | 0x80; save->CR3B = __svgalib_incrtc(0x3b); save->CR3C = __svgalib_incrtc(0x3c); save->CR43 = __svgalib_incrtc(0x43); save->CR5D = __svgalib_incrtc(0x5d); save->CR5E = __svgalib_incrtc(0x5e); save->CR65 = __svgalib_incrtc(0x65); /* Save sequencer extended regs for DCLK PLL programming */ save->SR10 = __svgalib_inseq(0x10); save->SR11 = __svgalib_inseq(0x11); save->SR12 = __svgalib_inseq(0x12); save->SR13 = __svgalib_inseq(0x13); save->SR29 = __svgalib_inseq(0x29); save->SR15 = __svgalib_inseq(0x15); save->SR18 = __svgalib_inseq(0x18);// __svgalib_outcrtc(0x53, cr53); __svgalib_outcrtc(0x3a, cr3a); __svgalib_outcrtc(0x66, cr66); return SAVAGE_TOTAL_REGS - VGA_TOTAL_REGS;}/* Set chipset-specific registers */static void savage_setregs(const unsigned char regs[], int mode){ int tmp; vgaS3VPtr restore = (vgaS3VPtr)(regs+VGA_TOTAL_REGS); savage_unlock();#if 0 /* Are we going to reenable STREAMS in this new mode? */ s3vPriv.STREAMSRunning = restore->CR67 & 0x0c; /* First reset GE to make sure nothing is going on */ outb(vgaCRIndex, 0x66); if(inb(vgaCRReg) & 0x01) S3SAVGEReset(0,__LINE__,__FILE__);#endif /* As per databook, always disable STREAMS before changing modes */ __svgalib_outcrtc(0x67, __svgalib_incrtc(0x67)&0xf3); __svgalib_outcrtc(0x66, restore->CR66); __svgalib_outcrtc(0x3a, restore->CR3A); __svgalib_outcrtc(0x31, restore->CR31); __svgalib_outcrtc(0x58, restore->CR58); __svgalib_outseq(0x08, 0x06); __svgalib_outseq(0x12, restore->SR12); __svgalib_outseq(0x13, restore->SR13); __svgalib_outseq(0x29, restore->SR29); __svgalib_outseq(0x15, restore->SR15);#if 0 /* Restore the standard VGA registers */ vgaHWRestore((vgaHWPtr)restore);#endif __svgalib_outcrtc(0x53, restore->CR53); __svgalib_outcrtc(0x5d, restore->CR5D); __svgalib_outcrtc(0x5e, restore->CR5E); __svgalib_outcrtc(0x3b, restore->CR3B); __svgalib_outcrtc(0x3c, restore->CR3C); __svgalib_outcrtc(0x43, restore->CR43); __svgalib_outcrtc(0x65, restore->CR65); /* Restore the desired video mode with CR67 */ __svgalib_outcrtc(0x67, 0x50 | (__svgalib_incrtc(0x67)&0xf3)); usleep(10000); __svgalib_outcrtc(0x67, restore->CR67&0xf3); __svgalib_outcrtc(0x34, restore->CR34); __svgalib_outcrtc(0x40, restore->CR40); __svgalib_outcrtc(0x42, restore->CR42); __svgalib_outcrtc(0x45, restore->CR45); __svgalib_outcrtc(0x50, restore->CR50); __svgalib_outcrtc(0x51, restore->CR51); __svgalib_outcrtc(0x36, restore->CR36); __svgalib_outcrtc(0x68, restore->CR68); __svgalib_outcrtc(0x69, restore->CR69); __svgalib_outcrtc(0x6f, restore->CR6F); __svgalib_outcrtc(0x33, restore->CR33); __svgalib_outcrtc(0x86, restore->CR86); __svgalib_outcrtc(0x88, restore->CR88); __svgalib_outcrtc(0x90, restore->CR90); __svgalib_outcrtc(0x91, restore->CR91); __svgalib_outcrtc(0xb0, restore->CRB0); __svgalib_outseq(0x08, 0x06); /* Restore extended sequencer regs for MCLK. SR10 == 255 indicates that * we should leave the default SR10 and SR11 values there. */ if (restore->SR10 != 255) { __svgalib_outseq(0x10, restore->SR10); __svgalib_outseq(0x11, restore->SR11); } /* Restore extended sequencer regs for DCLK */ __svgalib_outseq(0x12, restore->SR12); __svgalib_outseq(0x13, restore->SR13); __svgalib_outseq(0x29, restore->SR29); __svgalib_outseq(0x18, restore->SR18);#if 0 /* Load new m,n PLL values for DCLK & MCLK */ outb(0x3c4, 0x15); tmp = inb(0x3c5) & ~0x21; outb(0x3c5, tmp | 0x03); outb(0x3c5, tmp | 0x23); outb(0x3c5, tmp | 0x03); outb(0x3c5, restore->SR15);#else tmp = __svgalib_inseq(0x15) & ~0x21; __svgalib_outseq(0x15, tmp | 0x03); __svgalib_outseq(0x15, tmp | 0x23); __svgalib_outseq(0x15, tmp | 0x03); __svgalib_outseq(0x15, restore->SR15);#endif __svgalib_outseq(0x08, restore->SR8); /* Now write out CR67 in full, possibly starting STREAMS */ __svgalib_outcrtc(0x67, 0x50); usleep(10000); __svgalib_outcrtc(0x67, restore->CR67&0xf3); __svgalib_outcrtc(0x53, restore->CR53); __svgalib_outcrtc(0x66, restore->CR66); __svgalib_outcrtc(0x3a, restore->CR3A);}/* Return nonzero if mode is available */static int savage_modeavailable(int mode){ struct info *info; ModeTiming *modetiming; ModeInfo *modeinfo; if (IS_IN_STANDARD_VGA_DRIVER(mode)) return __svgalib_vga_driverspecs.modeavailable(mode); info = &__svgalib_infotable[mode]; if (savage_memory * 1024 < info->ydim * info->xbytes) return 0; modeinfo = __svgalib_createModeInfoStructureForSvgalibMode(mode); if(modeinfo->bytesPerPixel==3) return 0; modetiming = malloc(sizeof(ModeTiming)); if (__svgalib_getmodetiming(modetiming, modeinfo, cardspecs)) { free(modetiming); free(modeinfo); return 0; } free(modetiming); free(modeinfo); return SVGADRV;}/* Local, called by savage_setmode(). */#define BASE_FREQ 14.31818void savageCalcClock(long freq, int min_m, int min_n1, int max_n1, int min_n2, int max_n2, long freq_min, long freq_max, unsigned int *mdiv, unsigned int *ndiv, unsigned int *r){ double ffreq, ffreq_min, ffreq_max; double div, diff, best_diff; unsigned int m; unsigned char n1, n2; unsigned char best_n1=16+2, best_n2=2, best_m=125+2; ffreq = freq / 1000.0 / BASE_FREQ; ffreq_min = freq_min / 1000.0 / BASE_FREQ; ffreq_max = freq_max / 1000.0 / BASE_FREQ; if (ffreq < ffreq_min / (1<<max_n2)) { ffreq = ffreq_min / (1<<max_n2); } if (ffreq > ffreq_max / (1<<min_n2)) { ffreq = ffreq_max / (1<<min_n2); } /* work out suitable timings */ best_diff = ffreq; for (n2=min_n2; n2<=max_n2; n2++) { for (n1 = min_n1+2; n1 <= max_n1+2; n1++) { m = (int)(ffreq * n1 * (1<<n2) + 0.5) ; if (m < min_m+2 || m > 127+2) continue; div = (double)(m) / (double)(n1); if ((div >= ffreq_min) && (div <= ffreq_max)) { diff = ffreq - div / (1<<n2); if (diff < 0.0) diff = -diff; if (diff < best_diff) { best_diff = diff; best_m = m; best_n1 = n1; best_n2 = n2; } } } } *ndiv = best_n1 - 2; *r = best_n2; *mdiv = best_m - 2;}static void savage_initializemode(unsigned char *moderegs, ModeTiming * modetiming, ModeInfo * modeinfo, int mode){ int i, j, dclk, width, tmp; vgaS3VPtr new = (vgaS3VPtr)(moderegs+VGA_TOTAL_REGS); if(modeinfo->bitsPerPixel==16) { modetiming->HDisplay *=2; modetiming->HSyncStart *=2; modetiming->HSyncEnd *=2; modetiming->HTotal *=2; } __svgalib_setup_VGA_registers(moderegs, modetiming, modeinfo); tmp = __svgalib_incrtc(0x3a); if( 0 /*!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 = 0x09; /* Dis. 64k window, en. ENH maps */ /* Enables S3D graphic engine and PCI disconnects */ new->CR66 = 0x89; /* Now set linear addr. registers *//* LAW size: always 8 MB for Savage3D */ new->CR58 = (__svgalib_incrtc(0x58) & 0x80) | 0x13; new->CR58=0; /* seems to be 0 for paged mode and 0x13 for linear */ /* Now do clock PLL programming. Use the s3gendac function to get m,n *//* Also determine if we need doubling etc. */ dclk = modetiming->pixelClock; new->CR67 = 0x00; /* Defaults */ new->SR15 = 0x03 | 0x80; new->SR18 = 0x00; new->CR43 = 0x00; new->CR45 = 0x00; new->CR65 = 0x00; new->CR40 = __svgalib_incrtc(0x40) & 0xfe ; /* 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 0 if (OFLG_ISSET(OPTION_FIFO_AGGRESSIVE, &vga256InfoRec.options) || OFLG_ISSET(OPTION_FIFO_MODERATE, &vga256InfoRec.options) ||
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -