📄 laguna.c
字号:
/*Laguna chipset driver for cirrus logic 5462, 5464, 5465Only tested on 5464.Problems: mouse cursor does not work. secondary (mmio only) not tested. fifo threshold needs more tuning.*/#include <stdlib.h>#include <stdio.h> #include <string.h>#include <unistd.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"struct lagunahw { unsigned char crt[5]; unsigned char gra[3]; unsigned char seq[3]; unsigned char pal_state; unsigned char bclk; unsigned char tile; unsigned short tiling_control; unsigned short control; unsigned short format; unsigned short cur_x; unsigned short cur_y; unsigned short cur_preset; unsigned short cur_misc; unsigned short cur_address; unsigned short disp_thresh; unsigned int pcifc;};#define LAGUNAREG_SAVE(i) (VGA_TOTAL_REGS+i)#define LAGUNA_TOTAL_REGS (VGA_TOTAL_REGS + sizeof(struct lagunahw))enum { L5462=0, L5464, L5465};static int laguna_init(int, int, int);static void laguna_unlock(void);static void laguna_lock(void);void __svgalib_lagunaaccel_init(AccelSpecs * accelspecs, int bpp, int width_in_pixels);static int laguna_memory, laguna_chiptype;static int laguna_is_linear, laguna_linear_base, laguna_mmio_base;static CardSpecs *cardspecs;static inline unsigned int laguna_readb(int a) { return *(MMIO_POINTER+a);}static inline unsigned int laguna_readw(int a) { return *(unsigned short *)(MMIO_POINTER+a);}static inline unsigned int laguna_readl(int a) { return *(unsigned int *)(MMIO_POINTER+a);}static inline void laguna_writeb(int a, unsigned int d) { *(MMIO_POINTER+a)=d;}static inline void laguna_writew(int a, unsigned int d) { *(unsigned short *)(MMIO_POINTER+a)=d;}static inline void laguna_writel(int a, unsigned int d) { *(unsigned int *)(MMIO_POINTER+a)=d;}static void laguna_setpage(int page){ __svgalib_outgra(0x09,page*4);}static int __svgalib_laguna_inlinearmode(void){return laguna_is_linear;}/* Fill in chipset specific mode information */static void laguna_getmodeinfo(int mode, vga_modeinfo *modeinfo){ if(modeinfo->colors==16)return; modeinfo->maxpixels = laguna_memory*1024/modeinfo->bytesperpixel; modeinfo->maxlogicalwidth = 4088; modeinfo->startaddressrange = laguna_memory * 1024 - 1; modeinfo->haveblit = 0; modeinfo->flags &= ~HAVE_RWPAGE; if (modeinfo->bytesperpixel >= 1) { if(laguna_linear_base)modeinfo->flags |= CAPABLE_LINEAR; if (__svgalib_laguna_inlinearmode()) modeinfo->flags |= IS_LINEAR; }}/* Read and save chipset-specific registers */static int laguna_saveregs(unsigned char regs[]){ struct lagunahw *l=(struct lagunahw *)(regs+VGA_TOTAL_REGS); laguna_unlock(); l->crt[0]= __svgalib_incrtc(0x19); l->crt[1]= __svgalib_incrtc(0x1a); l->crt[2]= __svgalib_incrtc(0x1b); l->crt[3]= __svgalib_incrtc(0x1d); l->crt[4]= __svgalib_incrtc(0x1e); l->gra[0]= __svgalib_ingra(0x09); l->gra[1]= __svgalib_ingra(0x0a); l->gra[2]= __svgalib_ingra(0x0b); l->seq[0]= __svgalib_inseq(0x0e); l->seq[1]= __svgalib_inseq(0x1e); l->seq[2]= __svgalib_inseq(0x07); if(laguna_chiptype==L5465) l->tiling_control=laguna_readw(0x2c4); l->control=laguna_readw(0x402); if(laguna_chiptype==L5465) l->bclk=laguna_readb(0x2c0); else l->bclk=laguna_readb(0x8c); l->tile=laguna_readb(0x407); l->pal_state=laguna_readb(0xb0); l->format=laguna_readw(0xc0); l->cur_x=laguna_readw(0xe0); l->cur_y=laguna_readw(0xe2); l->cur_preset=laguna_readw(0xe4); l->cur_misc=laguna_readw(0xe6); l->cur_address=laguna_readw(0xe8); l->disp_thresh=laguna_readw(0xea); l->pcifc=laguna_readl(0x3fc); return LAGUNA_TOTAL_REGS - VGA_TOTAL_REGS;}/* Set chipset-specific registers */static void laguna_setregs(const unsigned char regs[], int mode){ struct lagunahw *l=(struct lagunahw *)(regs+VGA_TOTAL_REGS); laguna_unlock(); __svgalib_outcrtc(0x19,l->crt[0]); __svgalib_outcrtc(0x1a,l->crt[1]); __svgalib_outcrtc(0x1b,l->crt[2]); __svgalib_outcrtc(0x1d,l->crt[3]); __svgalib_outcrtc(0x1e,l->crt[4]); __svgalib_outgra(0x09,l->gra[0]); __svgalib_outgra(0x0a,l->gra[1]); __svgalib_outgra(0x0b,l->gra[2]); __svgalib_outseq(0x0e,l->seq[0]); __svgalib_outseq(0x1e,l->seq[1]); __svgalib_outseq(0x07,l->seq[2]); if(laguna_chiptype==L5465) laguna_writew(0x2c4,l->tiling_control); laguna_writew(0x402,l->control); if(laguna_chiptype==L5465) laguna_writeb(0x2c0,l->bclk); else laguna_writeb(0x8c,l->bclk); laguna_writew(0x407,l->tile); laguna_writew(0xb0,l->pal_state); laguna_writew(0xc0,l->format); laguna_writew(0xe0,l->cur_x); laguna_writew(0xe2,l->cur_y); laguna_writew(0xe4,l->cur_preset); laguna_writew(0xe6,l->cur_misc); laguna_writew(0xe8,l->cur_address); laguna_writew(0xea,l->disp_thresh); laguna_writel(0x3fc,l->pcifc);}/* Return nonzero if mode is available */static int laguna_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 (laguna_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;}/* Local, called by laguna_setmode(). */#define REF 14318static int laguna_findclock(int clock, int *on, int *om, int *op, int *opp){ int n, m, diff, best, bestm; *opp=0; while(clock<20000) { clock*=2; *opp=+1; } if(clock<40000) { clock *= 2; *op=1; } else *op=0; best=clock; bestm=5; for(m=6; m<30;m++) { n=clock*m/REF; if((n<64)||(n>127)) continue; diff=clock-(n*REF/m); if(diff<0)diff=-diff; if(diff<best) { best=diff; bestm=m; } } if((best==0) || (clock/best>100)) { *on=clock*bestm/REF; *om=bestm; return 0; } else { fprintf(stderr,"Can't find clock %iKHz.\n",clock); return -1; } }static void laguna_initializemode(unsigned char *moderegs, ModeTiming * modetiming, ModeInfo * modeinfo, int mode){ struct lagunahw *l=(struct lagunahw *)(moderegs+VGA_TOTAL_REGS); int hd, htot, hss, hse, hbs, hbe; int vd, vtot, vss, vse, vbs, vbe; int offset; int n,m,p,pp; __svgalib_setup_VGA_registers(moderegs, modetiming, modeinfo); if(laguna_chiptype==L5465) { l->tiling_control=laguna_readw(0x2c4); l->tiling_control &= ~0x80; /* disable tiling */ } l->control=laguna_readw(0x402) & 0x87ff; /* narrow tiles */ l->control |= 0x1000; /* disable tiling */ l->disp_thresh=laguna_readw(0xea)&0xffe0; l->disp_thresh &= 0x3fbf; /* 1-way interleave and narrow tiles */ switch(modeinfo->bitsPerPixel) { case 8: case 15: case 16: l->disp_thresh |= 0x10; break; case 24: case 32: l->disp_thresh |= 0x20; break; default: l->disp_thresh |= 0x18; } l->pcifc=laguna_readl(0x3fc); l->pcifc |= 0x10000000; if(laguna_chiptype==L5465) l->bclk=laguna_readb(0x2c0);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -