📄 nv3.c
字号:
/*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/types.h>#include <sys/mman.h> /* mmap */#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"#ifdef OSKIT#include "osenv.h"#endif#define NV3REG_SAVE(i) (VGA_TOTAL_REGS+i)#define NV3_TOTAL_REGS (VGA_TOTAL_REGS + 24 + 33 )#define PLL_INPUT_FREQ 13500 #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 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 unsigned long MMIOBASE, LINEARBASE;enum { NV3_chipset = 0};static void nv3_setpage(int page){__svgalib_outCR(0x1d,page << 1);__svgalib_outCR(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){ 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_inCR(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)]); __svgalib_outCR(0x1c,regs[88]); /* this enables banking at 0xa0000 */__svgalib_outCR(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; modeinfo = __svgalib_createModeInfoStructureForSvgalibMode(mode); if(modeinfo->bitsPerPixel==24)return 0; 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->greenWeight==5)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)]=
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -