📄 i740.c
字号:
/* i740 chipset driver written by Matan Ziv-Av. Only tested on a Hercules Terminator 2x/I Interlaced modes don't work yet.*/#include <stdlib.h>#include <stdio.h> #include <string.h>#include <unistd.h>#include <math.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"#include "i740_reg.h"typedef struct { unsigned char DisplayControl; unsigned char PixelPipeCfg0; unsigned char PixelPipeCfg1; unsigned char PixelPipeCfg2; unsigned char VideoClk2_M; unsigned char VideoClk2_N; unsigned char VideoClk2_MN_MSBs; unsigned char VideoClk2_DivisorSel; unsigned char PLLControl; unsigned char AddressMapping; unsigned char IOControl; unsigned char BitBLTControl; unsigned char ExtVertTotal; unsigned char ExtVertDispEnd; unsigned char ExtVertSyncStart; unsigned char ExtVertBlankStart; unsigned char ExtHorizTotal; unsigned char ExtHorizBlank; unsigned char ExtOffset; unsigned char InterlaceControl; unsigned char ExtStartAddr; unsigned char ExtStartAddrHi; unsigned int LMI_FIFO_Watermark;} vgaI740Rec, *vgaI740Ptr;#define I740REG_SAVE(i) (VGA_TOTAL_REGS+i)#define I740_TOTAL_REGS (VGA_TOTAL_REGS + 26)static int i740_init(int, int, int);static void i740_unlock(void);static void i740_lock(void);void __svgalib_i740accel_init(AccelSpecs * accelspecs, int bpp, int width_in_pixels);static int i740_memory, I740HasSGRAM;static int i740_is_linear, i740_linear_base, i740_mmio_base;static CardSpecs *cardspecs;static void i740_setpage(int page){ outb(XRX,14); outb(XRX+1,page);}static int __svgalib_i740_inlinearmode(void){return i740_is_linear;}/* Fill in chipset specific mode information */static void i740_getmodeinfo(int mode, vga_modeinfo *modeinfo){ if(modeinfo->colors==16)return; modeinfo->maxpixels = i740_memory*1024/modeinfo->bytesperpixel; modeinfo->maxlogicalwidth = 4088; modeinfo->startaddressrange = i740_memory * 1024 - 1; modeinfo->haveblit = 0; modeinfo->flags &= ~HAVE_RWPAGE; if (modeinfo->bytesperpixel >= 1) { if(i740_linear_base)modeinfo->flags |= CAPABLE_LINEAR; if (__svgalib_i740_inlinearmode()) modeinfo->flags |= IS_LINEAR; }}/* Read and save chipset-specific registers */static int i740_saveregs(unsigned char regs[]){ vgaI740Ptr save; i740_unlock(); save = (vgaI740Ptr)(regs+VGA_TOTAL_REGS); /* * The port I/O code necessary to read in the extended registers * into the fields of the vgaI740Rec structure goes here. */ outb(XRX, IO_CTNL); save->IOControl = inb(XRX+1); outb(XRX, ADDRESS_MAPPING); save->AddressMapping = inb(XRX+1); outb(XRX, BITBLT_CNTL); save->BitBLTControl = inb(XRX+1); outb(XRX, VCLK2_VCO_M); save->VideoClk2_M = inb(XRX+1); outb(XRX, VCLK2_VCO_N); save->VideoClk2_N = inb(XRX+1); outb(XRX, VCLK2_VCO_MN_MSBS); save->VideoClk2_MN_MSBs = inb(XRX+1); outb(XRX, VCLK2_VCO_DIV_SEL); save->VideoClk2_DivisorSel = inb(XRX+1); outb(XRX, PLL_CNTL); save->PLLControl = inb(XRX+1); save->ExtVertTotal = __svgalib_inCR(EXT_VERT_TOTAL); save->ExtVertDispEnd = __svgalib_inCR(EXT_VERT_DISPLAY); save->ExtVertSyncStart = __svgalib_inCR(EXT_VERT_SYNC_START); save->ExtVertBlankStart = __svgalib_inCR(EXT_VERT_BLANK_START); save->ExtHorizTotal = __svgalib_inCR(EXT_HORIZ_TOTAL); save->ExtHorizBlank = __svgalib_inCR(EXT_HORIZ_BLANK); save->ExtOffset = __svgalib_inCR(EXT_OFFSET); save->InterlaceControl = __svgalib_inCR(INTERLACE_CNTL); save->ExtStartAddr = __svgalib_inCR(EXT_START_ADDR); save->ExtStartAddrHi = __svgalib_inCR(EXT_START_ADDR_HI); outb(XRX, PIXPIPE_CONFIG_0); save->PixelPipeCfg0 = inb(XRX+1); outb(XRX, PIXPIPE_CONFIG_1); save->PixelPipeCfg1 = inb(XRX+1); outb(XRX, PIXPIPE_CONFIG_2); save->PixelPipeCfg2 = inb(XRX+1); outb(XRX, DISPLAY_CNTL); save->DisplayControl = inb(XRX+1); save->LMI_FIFO_Watermark = INREG(FWATER_BLC); return I740_TOTAL_REGS - VGA_TOTAL_REGS;}/* Set chipset-specific registers */static void i740_setregs(const unsigned char regs[], int mode){ int temp; vgaI740Ptr restore; i740_unlock(); restore = (vgaI740Ptr)(regs+VGA_TOTAL_REGS); outb(XRX, DRAM_EXT_CNTL); outb(XRX+1, DRAM_REFRESH_DISABLE); usleep(1000); /* Wait 1 ms */ /* Write the M, N and P values */ outb(XRX, VCLK2_VCO_M); outb(XRX+1, restore->VideoClk2_M); outb(XRX, VCLK2_VCO_N); outb(XRX+1, restore->VideoClk2_N); outb(XRX, VCLK2_VCO_MN_MSBS); outb(XRX+1, restore->VideoClk2_MN_MSBs); outb(XRX, VCLK2_VCO_DIV_SEL); outb(XRX+1, restore->VideoClk2_DivisorSel); outb(XRX, PIXPIPE_CONFIG_0); temp = inb(XRX+1); temp &= 0x7F; /* Save all but the 8 bit dac mode bit */ temp |= (restore->PixelPipeCfg0 & DAC_8_BIT); outb(XRX, PIXPIPE_CONFIG_0); outb(XRX+1, temp); __svgalib_outCR(EXT_VERT_TOTAL, restore->ExtVertTotal); __svgalib_outCR(EXT_VERT_DISPLAY, restore->ExtVertDispEnd); __svgalib_outCR(EXT_VERT_SYNC_START, restore->ExtVertSyncStart); __svgalib_outCR(EXT_VERT_BLANK_START, restore->ExtVertBlankStart); __svgalib_outCR(EXT_HORIZ_TOTAL, restore->ExtHorizTotal); __svgalib_outCR(EXT_HORIZ_BLANK, restore->ExtHorizBlank); __svgalib_outCR(EXT_OFFSET, restore->ExtOffset); __svgalib_outCR(EXT_START_ADDR, restore->ExtStartAddr); __svgalib_outCR(EXT_START_ADDR_HI, restore->ExtStartAddrHi); temp=__svgalib_inCR(INTERLACE_CNTL); temp &= ~INTERLACE_ENABLE; temp |= restore->InterlaceControl; __svgalib_outCR(INTERLACE_CNTL, temp); outb(XRX, ADDRESS_MAPPING); temp = inb(XRX+1); temp &= 0xE0; /* Save reserved bits 7:5 */ temp |= restore->AddressMapping; outb(XRX, ADDRESS_MAPPING); outb(XRX+1, temp); outb(XRX, IO_CTNL); temp = inb(XRX+1); temp &= ~(EXTENDED_ATTR_CNTL|EXTENDED_CRTC_CNTL); temp |= restore->IOControl; outb(XRX, IO_CTNL); outb(XRX+1, temp); outb(XRX, BITBLT_CNTL); temp = inb(XRX+1); temp &= ~COLEXP_MODE; temp |= restore->BitBLTControl; outb(XRX, BITBLT_CNTL); outb(XRX+1, temp); outb(XRX, DISPLAY_CNTL); temp = inb(XRX+1); temp &= ~(VGA_WRAP_MODE | GUI_MODE); temp |= restore->DisplayControl; outb(XRX, DISPLAY_CNTL); outb(XRX+1, temp); outb(XRX, PIXPIPE_CONFIG_0); temp = inb(XRX+1); temp &= 0x64; /* Save reserved bits 6:5,2 */ temp |= restore->PixelPipeCfg0; outb(XRX, PIXPIPE_CONFIG_0); outb(XRX+1, temp); outb(XRX, PIXPIPE_CONFIG_2); temp = inb(XRX+1); temp &= 0xF3; /* Save reserved bits 7:4,1:0 */ temp |= restore->PixelPipeCfg2; outb(XRX, PIXPIPE_CONFIG_2); outb(XRX+1, temp); outb(XRX, PLL_CNTL); temp = inb(XRX+1); temp &= ~PLL_MEMCLK_SEL;#if 1 temp = restore->PLLControl; /* To fix the 2.3X BIOS problem */#else temp |= restore->PLLControl;#endif outb(XRX, PLL_CNTL); outb(XRX+1, temp); outb(XRX, PIXPIPE_CONFIG_1); temp = inb(XRX+1); temp &= ~DISPLAY_COLOR_MODE; temp |= restore->PixelPipeCfg1; outb(XRX, PIXPIPE_CONFIG_1); outb(XRX+1, temp); temp = INREG(FWATER_BLC); temp &= ~(LMI_BURST_LENGTH | LMI_FIFO_WATERMARK); temp |= restore->LMI_FIFO_Watermark; OUTREG(FWATER_BLC, temp); /* Turn on DRAM Refresh */ outb(XRX, DRAM_EXT_CNTL); outb(XRX+1, DRAM_REFRESH_60HZ); usleep(50000);}/* Return nonzero if mode is available */static int i740_modeavailable(int mode){ struct info *info; ModeTiming *modetiming; ModeInfo *modeinfo; if ((mode < G640x480x256 ) || mode == G720x348x2) return __svgalib_vga_driverspecs.modeavailable(mode); info = &__svgalib_infotable[mode]; if (i740_memory * 1024 < info->ydim * info->xbytes) return 0; modeinfo = __svgalib_createModeInfoStructureForSvgalibMode(mode); modetiming = malloc(sizeof(ModeTiming)); if (__svgalib_getmodetiming(modetiming, modeinfo, cardspecs)) { free(modetiming); free(modeinfo); return 0; } free(modetiming); free(modeinfo); return SVGADRV;}static unsigned int I740CalcFIFO(double freq, int bpp){ /* * Would like to calculate these values automatically, but a generic * algorithm does not seem possible. Note: These FIFO water mark * values were tested on several cards and seem to eliminate the * all of the snow and vertical banding, but fine adjustments will * probably be required for other cards. */ unsigned int wm = 0x18120000; switch (bpp) { case 8: if (I740HasSGRAM) { if (freq > 200) wm = 0x18120000; else if (freq > 175) wm = 0x16110000; else if (freq > 135) wm = 0x120E0000; else wm = 0x100D0000; } else { if (freq > 200) wm = 0x18120000; else if (freq > 175) wm = 0x16110000; else if (freq > 135) wm = 0x120E0000; else wm = 0x100D0000; } break; case 16: if (I740HasSGRAM) { if (freq > 140) wm = 0x2C1D0000; else if (freq > 120) wm = 0x2C180000; else if (freq > 100) wm = 0x24160000; else if (freq > 90) wm = 0x18120000; else if (freq > 50) wm = 0x16110000; else if (freq > 32) wm = 0x13100000; else wm = 0x120E0000; } else { if (freq > 160) wm = 0x28200000; else if (freq > 140) wm = 0x2A1E0000; else if (freq > 130) wm = 0x2B1A0000; else if (freq > 120) wm = 0x2C180000; else if (freq > 100) wm = 0x24180000; else if (freq > 90) wm = 0x18120000; else if (freq > 50) wm = 0x16110000; else if (freq > 32) wm = 0x13100000; else wm = 0x120E0000; } break; case 24: if (I740HasSGRAM) { if (freq > 130) wm = 0x31200000; else if (freq > 120) wm = 0x2E200000; else if (freq > 100) wm = 0x2C1D0000; else if (freq > 80) wm = 0x25180000; else if (freq > 64) wm = 0x24160000; else if (freq > 49) wm = 0x18120000; else if (freq > 32) wm = 0x16110000; else wm = 0x13100000; } else { if (freq > 120) wm = 0x311F0000; else if (freq > 100) wm = 0x2C1D0000; else if (freq > 80) wm = 0x25180000; else if (freq > 64) wm = 0x24160000; else if (freq > 49) wm = 0x18120000; else if (freq > 32) wm = 0x16110000; else wm = 0x13100000; } break; case 32: if (I740HasSGRAM) { if (freq > 80) wm = 0x2A200000; else if (freq > 60) wm = 0x281A0000; else if (freq > 49) wm = 0x25180000; else if (freq > 32) wm = 0x18120000; else wm = 0x16110000; } else { if (freq > 80) wm = 0x29200000; else if (freq > 60) wm = 0x281A0000; else if (freq > 49) wm = 0x25180000; else if (freq > 32) wm = 0x18120000; else wm = 0x16110000; } break; } return wm;}#define MAX_VCO_FREQ 450.0#define TARGET_MAX_N 30#define REF_FREQ 66.66666666667#define CALC_VCLK(m,n,p,d) \ (double)m / ((double)n * (1 << p)) * (4 << (d << 1)) * REF_FREQstatic voidI740CalcVCLK(double freq ,int *M, int *N, int *MN, int *DIVSEL ){ int m, n, p, d; double f_out; double f_err; double f_vco; int m_best = 0, n_best = 0, p_best = 0, d_best = 0; double f_target = freq; double err_max = 0.005; double err_target = 0.001; double err_best = 999999.0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -