nv3.c
来自「linux 下svgalib编的一个界面程序示例」· C语言 代码 · 共 736 行 · 第 1/2 页
C
736 行
/*Riva 128 driver - Matan Ziv-Av zivav@cs.bgu.ac.ilplease report problems to me,This driver is based on the XFREE86 nv3 driver, developed byDavid J. Mckay.I used the file cirrus.c in this directory as a skeleton.there are still the following problems: * no 24bit modes. (maybe the hardware does not support) * pageflipping (in threeDKit) does not work. * no acceleration (is there a program that uses it anyway?).*/#include <stdlib.h>#include <stdio.h> /* for printf */#include <string.h> /* for memset */#include <sys/mman.h> #include <fcntl.h>#include <math.h>#include <unistd.h>#include "vga.h"#include "libvga.h"#include "driver.h"/* New style driver interface. */#include "timing.h"#include "vgaregs.h"#include "interface.h"#include "accel.h"#include "nv3ref.h"#include "nvreg.h"#include "vgapci.h"#define NV3REG_SAVE(i) (VGA_TOTAL_REGS+i)#define NV3_TOTAL_REGS (VGA_TOTAL_REGS + 24 + 33 )#define M_MIN 7#define M_MAX 13#define P_MIN 0#define P_MAX 7 /* Not sure about this. Could be 4 */#define SetBitField(value,from,to) SetBF(to,GetBF(value,from))#define SetBit(n) (1<<(n))#define Set8Bits(value) ((value)&0xff)static volatile unsigned *nvPFBPort;static volatile unsigned *nvPRAMDACPort;static volatile unsigned *nvPEXTDEVPort;static int nv3_init(int, int, int);static void nv3_unlock(void);void __svgalib_nv3accel_init(AccelSpecs * accelspecs, int bpp, int width_in_pixels);static int nv3_memory,nv3_chiptype;static int nv3_is_linear;static CardSpecs *cardspecs;static int PLL_INPUT_FREQ;static unsigned long MMIOBASE=0, LINEARBASE;enum { Riva128 = 0, RivaTNT, GEFORCE};static void nv3_setpage(int page){__svgalib_outcrtc(0x1d,page << 1);__svgalib_outcrtc(0x1e,page << 1);}static int __svgalib_nv3_inlinearmode(void){return nv3_is_linear;}/* Fill in chipset specific mode information */static void nv3_getmodeinfo(int mode, vga_modeinfo *modeinfo){ if(modeinfo->colors==16)return; modeinfo->maxpixels = nv3_memory*1024/modeinfo->bytesperpixel; modeinfo->maxlogicalwidth = 4088; modeinfo->startaddressrange = nv3_memory * 1024 - 1; modeinfo->haveblit = 0; modeinfo->flags &= ~HAVE_RWPAGE; if (modeinfo->bytesperpixel >= 1) { modeinfo->flags |= CAPABLE_LINEAR; if (__svgalib_nv3_inlinearmode()) modeinfo->flags |= IS_LINEAR; }}/* Read and save chipset-specific registers */static int nv3_saveregs(unsigned char regs[]){ unsigned long k; int i; nv3_unlock(); /* May be locked again by other programs (e.g. X) */ regs[NV3REG_SAVE(0)] = PCRTC_Read(REPAINT0); regs[NV3REG_SAVE(1)] = PCRTC_Read(REPAINT1); regs[NV3REG_SAVE(2)] = PCRTC_Read(EXTRA); regs[NV3REG_SAVE(3)] = PCRTC_Read(PIXEL); regs[NV3REG_SAVE(4)] = PCRTC_Read(HORIZ_EXTRA); regs[NV3REG_SAVE(5)] = PCRTC_Read(FIFO_CONTROL); regs[NV3REG_SAVE(6)] = PCRTC_Read(FIFO); regs[NV3REG_SAVE(7)] = 0; k = PFB_Read(CONFIG_0) ; regs[NV3REG_SAVE(8)] = k&0xff; regs[NV3REG_SAVE(9)] = (k >> 8)&0xff; regs[NV3REG_SAVE(10)] = (k >> 16) & 0xff ; regs[NV3REG_SAVE(11)] = ( k >> 24 ) & 0xff ; k = PRAMDAC_Read(VPLL_COEFF); regs[NV3REG_SAVE(12)] = k&0xff; regs[NV3REG_SAVE(13)] = (k >> 8)&0xff; regs[NV3REG_SAVE(14)] = (k >> 16) & 0xff ; regs[NV3REG_SAVE(15)] = ( k >> 24 ) & 0xff ; k = PRAMDAC_Read(PLL_COEFF_SELECT); regs[NV3REG_SAVE(16)] = k&0xff; regs[NV3REG_SAVE(17)] = (k >> 8)&0xff; regs[NV3REG_SAVE(18)] = (k >> 16) & 0xff ; regs[NV3REG_SAVE(19)] = ( k >> 24 ) & 0xff ; k = PRAMDAC_Read(GENERAL_CONTROL); regs[NV3REG_SAVE(20)] = k&0xff; regs[NV3REG_SAVE(21)] = (k >> 8)&0xff; regs[NV3REG_SAVE(22)] = (k >> 16) & 0xff ; regs[NV3REG_SAVE(23)] = ( k >> 24 ) & 0xff ; for(i=0x18;i<0x38;i++)regs[84+i-0x18]=__svgalib_incrtc(i); return NV3_TOTAL_REGS - VGA_TOTAL_REGS;}/* Set chipset-specific registers */static void nv3_setregs(const unsigned char regs[], int mode){ unsigned long k ; nv3_unlock(); /* May be locked again by other programs (eg. X) */ PCRTC_Write(REPAINT0,regs[NV3REG_SAVE(0)]); PCRTC_Write(REPAINT1,regs[NV3REG_SAVE(1)]); PCRTC_Write(EXTRA,regs[NV3REG_SAVE(2)]); PCRTC_Write(PIXEL,regs[NV3REG_SAVE(3)]); PCRTC_Write(HORIZ_EXTRA,regs[NV3REG_SAVE(4)]); PCRTC_Write(FIFO_CONTROL,regs[NV3REG_SAVE(5)]); /* PCRTC_Write(FIFO,regs[NV3REG_SAVE(6)]); */ __svgalib_outcrtc(0x1c,regs[88]); /* this enables banking at 0xa0000 */ __svgalib_outcrtc(0x1d,regs[89]); __svgalib_outcrtc(0x1e,regs[90]); __svgalib_outcrtc(0x31,0); /* disable cursor */ k=regs[NV3REG_SAVE(8)]+(regs[NV3REG_SAVE(9)] << 8)+(regs[NV3REG_SAVE(10)] << 16)+(regs[NV3REG_SAVE(11)] << 24); PFB_Write(CONFIG_0,k); k=regs[NV3REG_SAVE(12)]+(regs[NV3REG_SAVE(13)] << 8)+(regs[NV3REG_SAVE(14)] << 16)+(regs[NV3REG_SAVE(15)] << 24); PRAMDAC_Write(VPLL_COEFF,k); k=regs[NV3REG_SAVE(16)]+(regs[NV3REG_SAVE(17)] << 8)+(regs[NV3REG_SAVE(18)] << 16)+(regs[NV3REG_SAVE(19)] << 24); PRAMDAC_Write(PLL_COEFF_SELECT,k); k=regs[NV3REG_SAVE(20)]+(regs[NV3REG_SAVE(21)] << 8)+(regs[NV3REG_SAVE(22)] << 16)+(regs[NV3REG_SAVE(23)] << 24); PRAMDAC_Write(GENERAL_CONTROL,k);}/* Return nonzero if mode is available */static int nv3_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 (nv3_memory * 1024 < info->ydim * info->xbytes) return 0; modeinfo = __svgalib_createModeInfoStructureForSvgalibMode(mode); if(modeinfo->bitsPerPixel==24) { free(modeinfo); return 0; } modetiming = malloc(sizeof(ModeTiming)); if (__svgalib_getmodetiming(modetiming, modeinfo, cardspecs)) { free(modetiming); free(modeinfo); return 0; } free(modetiming); free(modeinfo); return SVGADRV;}static int NV3ClockSelect(float clockIn,float *clockOut,int *mOut, int *nOut,int *pOut);static int CalculateCRTC(ModeTiming *mode, ModeInfo *modeinfo, unsigned char *moderegs){ int bpp=modeinfo->bitsPerPixel/8, horizDisplay = (mode->CrtcHDisplay/8) - 1, horizStart = (mode->CrtcHSyncStart/8) - 1, horizEnd = (mode->CrtcHSyncEnd/8) - 1, horizTotal = (mode->CrtcHTotal/8) - 1, vertDisplay = mode->CrtcVDisplay - 1, vertStart = mode->CrtcVSyncStart - 1, vertEnd = mode->CrtcVSyncEnd - 1, vertTotal = mode->CrtcVTotal - 2; /* Calculate correct value for offset register */ moderegs[0x13]=((modeinfo->width/8)*bpp)&0xff; /* Extra bits for CRTC offset register */ moderegs[NV3REG_SAVE(0)]= SetBitField((modeinfo->width/8)*bpp,10:8,7:5); /* The NV3 manuals states that for native modes, there should be no * borders. This code should also be tidied up to use symbolic names */ moderegs[0x0]=Set8Bits(horizTotal - 4); moderegs[0x1]=Set8Bits(horizDisplay); moderegs[0x2]=Set8Bits(horizDisplay); moderegs[0x3]=SetBitField(horizTotal,4:0,4:0) | SetBit(7); moderegs[0x4]=Set8Bits(horizStart); moderegs[0x5]=SetBitField(horizTotal,5:5,7:7)| SetBitField(horizEnd,4:0,4:0); moderegs[0x6]=SetBitField(vertTotal,7:0,7:0); moderegs[0x7]=SetBitField(vertTotal,8:8,0:0)| SetBitField(vertDisplay,8:8,1:1)| SetBitField(vertStart,8:8,2:2)| SetBitField(vertDisplay,8:8,3:3)| SetBit(4)| SetBitField(vertTotal,9:9,5:5)| SetBitField(vertDisplay,9:9,6:6)| SetBitField(vertStart,9:9,7:7); moderegs[0x9]= SetBitField(vertDisplay,9:9,5:5) | SetBit(6); moderegs[0x10]= Set8Bits(vertStart); moderegs[0x11]= SetBitField(vertEnd,3:0,3:0) | SetBit(5); moderegs[0x12]= Set8Bits(vertDisplay); moderegs[0x15]= Set8Bits(vertDisplay); moderegs[0x16]= Set8Bits(vertTotal + 1); moderegs[NV3REG_SAVE(2)]= SetBitField(horizTotal,6:6,4:4) | SetBitField(vertDisplay,10:10,3:3) | SetBitField(vertStart,10:10,2:2) | SetBitField(vertDisplay,10:10,1:1) | SetBitField(vertTotal,10:10,0:0); if(mode->flags & DOUBLESCAN) moderegs[0x9]|=0x80; /* I think this should be SetBitField(horizTotal,8:8,0:0), but this * doesn't work apparently. Why 260 ? 256 would make sense. */ moderegs[NV3REG_SAVE(4)]= (horizTotal < 260 ? 0 : 1); return 1;}/* Set a mode *//* Local, called by nv3_setmode(). */static void nv3_initializemode(unsigned char *moderegs, ModeTiming * modetiming, ModeInfo * modeinfo, int mode){ long k; int m,n,p; float clockIn=(float)modetiming->pixelClock; float clockOut; int pixelDepth; nv3_saveregs(moderegs); __svgalib_setup_VGA_registers(moderegs, modetiming, modeinfo); if(!NV3ClockSelect(clockIn,&clockOut,&m,&n,&p)) {return ;} k=PRAMDAC_Val(VPLL_COEFF_NDIV,n) | PRAMDAC_Val(VPLL_COEFF_MDIV,m) | PRAMDAC_Val(VPLL_COEFF_PDIV,p); moderegs[NV3REG_SAVE(12)] = k&0xff; moderegs[NV3REG_SAVE(13)] = (k >> 8)&0xff; moderegs[NV3REG_SAVE(14)] = (k >> 16) & 0xff ; moderegs[NV3REG_SAVE(15)] = ( k >> 24 ) & 0xff ; CalculateCRTC(modetiming,modeinfo,moderegs); moderegs[NV3REG_SAVE(1)]= PCRTC_Val(REPAINT1_LARGE_SCREEN,modetiming->CrtcHDisplay<1280) | PCRTC_Def(REPAINT1_PALETTE_WIDTH,6BITS);/* The new xfree driver (from nVidia) calculates those in some twisted way, but I leave it for now */ moderegs[NV3REG_SAVE(5)]=0x83; moderegs[NV3REG_SAVE(6)]=0x22; /* PixelFormat controls how many bits per pixel. * There is another register in the * DAC which controls if mode is 5:5:5 or 5:6:5 */ pixelDepth=(modeinfo->bitsPerPixel+1)/8; if(pixelDepth>3) pixelDepth=3; moderegs[NV3REG_SAVE(3)]=pixelDepth; k= PRAMDAC_Def(GENERAL_CONTROL_IDC_MODE,GAMMA)| PRAMDAC_Val(GENERAL_CONTROL_565_MODE,modeinfo->greenWeight==6)| PRAMDAC_Def(GENERAL_CONTROL_TERMINATION,37OHM)| PRAMDAC_Def(GENERAL_CONTROL_BPC,6BITS)| PRAMDAC_Def(GENERAL_CONTROL_VGA_STATE,SEL); /* Not sure about this */ if(modeinfo->bitsPerPixel>8)k|=PRAMDAC_Def(GENERAL_CONTROL_BPC,8BITS); moderegs[NV3REG_SAVE(20)] = k&0xff; moderegs[NV3REG_SAVE(21)] = (k >> 8)&0xff; moderegs[NV3REG_SAVE(22)] = (k >> 16) & 0xff ; moderegs[NV3REG_SAVE(23)] = ( k >> 24 ) & 0xff ; switch(nv3_chiptype){ case Riva128: k=PRAMDAC_Def(PLL_COEFF_SELECT_MPLL_SOURCE,PROG)| PRAMDAC_Def(PLL_COEFF_SELECT_VPLL_SOURCE,PROG)| PRAMDAC_Def(PLL_COEFF_SELECT_VCLK_RATIO,DB2); break; case RivaTNT: case GEFORCE: k=0x10000700; break; }; moderegs[NV3REG_SAVE(16)] = k&0xff; moderegs[NV3REG_SAVE(17)] = (k >> 8)&0xff; moderegs[NV3REG_SAVE(18)] = (k >> 16) & 0xff ; moderegs[NV3REG_SAVE(19)] = ( k >> 24 ) & 0xff ; /* Disable Tetris tiling for now. This looks completely mad but could * give some significant performance gains. Will perhaps experiment * later on with this stuff! */ if(nv3_chiptype<GEFORCE) { k= PFB_Val(CONFIG_0_RESOLUTION,((modeinfo->lineWidth+31)/32))| PFB_Val(CONFIG_0_PIXEL_DEPTH,pixelDepth)| PFB_Def(CONFIG_0_TILING,ENABLED); moderegs[NV3REG_SAVE(8)] = k&0xff; moderegs[NV3REG_SAVE(9)] = (k >> 8)&0xff; moderegs[NV3REG_SAVE(10)] = (k >> 16) & 0xff ; moderegs[NV3REG_SAVE(11)] = ( k >> 24 ) & 0xff ; } moderegs[88]=28; if(modeinfo->greenWeight==5){moderegs[NV3REG_SAVE(21)]&=0xef;}; nv3_is_linear=0;return ;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?