⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 i740.c

📁 linux 下svgalib编的一个界面程序示例
💻 C
📖 第 1 页 / 共 2 页
字号:
/* 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 + -