📄 cirrus.c
字号:
/* VGAlib version 1.2 - (c) 1993 Tommy Frandsen *//* *//* This library is free software; you can redistribute it and/or *//* modify it without any restrictions. This library is distributed *//* in the hope that it will be useful, but without any warranty. *//* Cirrus support Copyright (C) 1993 Harm Hanemaayer *//* * Dec 1994: * * Mode setting rewritten with more SVGA generalization and increased * flexibility. Supports 542x/543x. * Uses interfaces in timing.h and vgaregs.h. Only saves/restores * extended registers that are actually changed for SVGA modes. */#include <stdlib.h>#include <stdio.h> /* for printf */#include <unistd.h>#include <string.h> /* for memset */#include "vga.h"#include "libvga.h"#include "driver.h"/* Enable support for > 85 MHz dot clocks on the 5434. */#define SUPPORT_5434_PALETTE_CLOCK_DOUBLING/* Use the special clocking mode for all dot clocks at 256 colors, not *//* just those > 85 MHz, for debugging. *//* #define ALWAYS_USE_5434_PALETTE_CLOCK_DOUBLING *//* New style driver interface. */#include "timing.h"#include "vgaregs.h"#include "interface.h"#include "accel.h"#include "vgapci.h"#define CIRRUSREG_GR(i) (VGA_TOTAL_REGS + i - VGA_GRAPHICS_COUNT)#define CIRRUSREG_SR(i) (VGA_TOTAL_REGS + 5 + i - VGA_SEQUENCER_COUNT)#define CIRRUSREG_CR(i) (VGA_TOTAL_REGS + 5 + 27 + i - VGA_CRTC_COUNT)#define CIRRUSREG_DAC (VGA_TOTAL_REGS + 5 + 27 + 15)#define CIRRUS_TOTAL_REGS (VGA_TOTAL_REGS + 5 + 27 + 15 + 1)/* Indices into mode register array. */#define CIRRUS_GRAPHICSOFFSET1 CIRRUSREG_GR(0x09)#define CIRRUS_GRAPHICSOFFSET2 CIRRUSREG_GR(0x0A)#define CIRRUS_GRB CIRRUSREG_GR(0x0B)#define CIRRUS_SR7 CIRRUSREG_SR(0x07)#define CIRRUS_VCLK3NUMERATOR CIRRUSREG_SR(0x0E)#define CIRRUS_DRAMCONTROL CIRRUSREG_SR(0x0F)#define CIRRUS_PERFTUNING CIRRUSREG_SR(0x16)#define CIRRUS_SR17 CIRRUSREG_SR(0x17)#define CIRRUS_VCLK3DENOMINATOR CIRRUSREG_SR(0x1E)#define CIRRUS_MCLKREGISTER CIRRUSREG_SR(0x1F)#define CIRRUS_CR19 CIRRUSREG_CR(0x19)#define CIRRUS_CR1A CIRRUSREG_CR(0x1A)#define CIRRUS_CR1B CIRRUSREG_CR(0x1B)#define CIRRUS_CR1D CIRRUSREG_CR(0x1D)#define CIRRUS_HIDDENDAC CIRRUSREG_DAC/* Efficient chip type checks. */#define CHECKCHIP1(c1) ((1 << cirrus_chiptype) & (1 << c1))#define CHECKCHIP2(c1, c2) ((1 << cirrus_chiptype) & ((1 << c1) | (1 << c2)))#define CHECKCHIP3(c1, c2, c3) ((1 << cirrus_chiptype) & ((1 << c1) \ | (1 << c2) | (1 << c3)))#define CHECKCHIP4(c1, c2, c3, c4) ((1 << cirrus_chiptype) & ((1 << c1) \ | (1 << c2) | (1 << c3) | (1 << c4)))#define CHECKCHIP5(c1, c2, c3, c4, c5) ((1 << cirrus_chiptype) & \ ((1 << c1) | (1 << c2) | (1 << c3) | (1 << c4) | (1 << c5)))#define CHECKCHIP6(c1, c2, c3, c4, c5, c6) ((1 << cirrus_chiptype) & \ ((1 << c1) | (1 << c2) | (1 << c3) | (1 << c4) | (1 << c5) \ | (1 << c6)))#define CHECKCHIP7(c1, c2, c3, c4, c5, c6, c7) ((1 << cirrus_chiptype) & \ ((1 << c1) | (1 << c2) | (1 << c3) | (1 << c4) | (1 << c5) \ | (1 << c6) | (1 << c7))) #define CHECKCHIP8(c1, c2, c3, c4, c5, c6, c7, c8) ((1 << cirrus_chiptype) & \ ((1 << c1) | (1 << c2) | (1 << c3) | (1 << c4) | (1 << c5) \ | (1 << c6) | (1 << c7) | (1 << c8)))#define CHECKCHIP9(c1, c2, c3, c4, c5, c6, c7, c8, c9) ((1 << cirrus_chiptype) & \ ((1 << c1) | (1 << c2) | (1 << c3) | (1 << c4) | (1 << c5) \ | (1 << c6) | (1 << c7) | (1 << c8) | (1 << c9)))#define CHECKCHIPGREATEREQUAL(c) (cirrus_chiptype >= c)#define CHECKCHIPNOTEQUAL(c) (cirrus_chiptype != c)#define CHIP_HAS_CR1D() \ CHECKCHIP4(CLGD5429, CLGD5430, CLGD5434, CLGD5436)#define CHIP_HAS_GRC_AND_GRD() \ CHECKCHIP4(CLGD5424, CLGD5426, CLGD5428, CLGD5429)#define CHIP_HAS_GRE() \ CHECKCHIP5(CLGD5428, CLGD5429, CLGD5430, CLGD5434, CLGD5436)#define CHIP_HAS_GR10_AND_GR11() \ CHECKCHIP7(CLGD5424, CLGD5426, CLGD5428, CLGD5429, CLGD5430, CLGD5434, CLGD5436)#define CHIP_HAS_BLTTRANSPARENTCOLOR() \ CHECKCHIP2(CLGD5426, CLGD5428)#define CHIP_HAS_PERFTUNINGREGISTER() \ CHECKCHIP7(CLGD5424, CLGD5426, CLGD5428, CLGD5429, CLGD5430, CLGD5434, CLGD5436)#define CHIP_HAS_MCLK_REGISTER() \ CHECKCHIP9(CLGD5420B, CLGD5422C, CLGD5424, CLGD5426, CLGD5428, \ CLGD5429, CLGD5430, CLGD5434, CLGD5436)#define CHIP_HAS_32BIT_DRAM_BUS() \ CHECKCHIPGREATEREQUAL(CLGD5420B)#define CHIP_HAS_64BIT_DRAM_BUS() \ CHECKCHIP3(CLGD5434, CLGD5436, CLGD7548)#define CHIP_HAS_HIDDENDAC() \ CHECKCHIPGREATEREQUAL(CLGD5420B)#define CHIP_HAS_ACCELERATION() \ CHECKCHIPNOTEQUAL(CLGD5420B)#define CHIP_HAS_SR17() \ CHECKCHIPGREATEREQUAL(CLGD5422)#define CHIP_USE_SR17() \ CHECKCHIPGREATEREQUAL(CLGD5429)/* CLOCK_FACTOR is double the osc freq in kHz (osc = 14.31818 MHz) */#define CLOCK_FACTOR 28636/* clock in kHz is (numer * CLOCK_FACTOR / (denom & 0x3E)) >> (denom & 1) */#define CLOCKVAL(n, d) \ ((((n) & 0x7F) * CLOCK_FACTOR / ((d) & 0x3E)) >> ((d) & 1))static int cirrus_init(int, int, int);static void cirrus_unlock(void);void __svgalib_cirrusaccel_init(AccelSpecs * accelspecs, int bpp, int width_in_pixels);static int cirrus_memory;static int cirrus_chiptype;static int cirrus_chiprev;static int cirrus_pci_linear = 0;static unsigned char actualMCLK, programmedMCLK;static int DRAMbandwidth, DRAMbandwidthLimit;static CardSpecs *cardspecs;#define NU_FIXED_CLOCKS 21/* 12.588 clock (0x33, 0x3B) replaced with 12.599 (0x2C, 0x33). */static int cirrus_fixed_clocks[NU_FIXED_CLOCKS] ={ 12599, 18000, 19600, 25227, 28325, 31500, 36025, 37747, 39992, 41164, 45076, 49867, 64983, 72163, 75000, 80013, 85226, 89998, 95019, 100226, 108035};static unsigned char fixed_clock_numerator[NU_FIXED_CLOCKS] ={ 0x2C, 0x27, 0x28, 0x4A, 0x5B, 0x42, 0x4E, 0x3A, 0x51, 0x45, 0x55, 0x65, 0x76, 0x7E, 0x6E, 0x5F, 0x7D, 0x58, 0x49, 0x46, 0x53};static unsigned char fixed_clock_denominator[NU_FIXED_CLOCKS] ={ 0x33, 0x3e, 0x3a, 0x2B, 0x2F, 0x1F, 0x3E, 0x17, 0x3A, 0x30, 0x36, 0x3A, 0x34, 0x32, 0x2A, 0x22, 0x2A, 0x1C, 0x16, 0x14, 0x16};/* * It looks like the 5434 palette clock doubling mode doensn't like * clocks like (0x7B, 0x20), whereas (0x53, 0x16) is OK. */enum { CLGD5420 = 0, CLGD7548, CLGD5420B, CLGD5422, CLGD5422C, CLGD5424, CLGD5426, CLGD5428, CLGD5429, CLGD5430, CLGD5434, CLGD5436};int __svgalib_cirrus_inlinearmode(void){ outb(SEQ_I, 0x07); return (inb(SEQ_D) & 0xf0) != 0;}/* Fill in chipset specific mode information */static void cirrus_getmodeinfo(int mode, vga_modeinfo * modeinfo){ if (modeinfo->bytesperpixel > 0) modeinfo->maxpixels = cirrus_memory * 1024 / modeinfo->bytesperpixel; else /* 16-color SVGA mode */ /* Value taken from the air. */ modeinfo->maxpixels = cirrus_memory * 2048; modeinfo->maxlogicalwidth = 4088;#if 0 if (mode != G320x200x256) { /* No need to check for 320x200x256, we now have a special */ /* SVGA-derived 320x200x256 mode that fully supports page */ /* flipping etc. */#endif modeinfo->startaddressrange = cirrus_memory * 1024 - 1; modeinfo->haveblit = 0;#if 0 } else { modeinfo->startaddressrange = 0xffff; modeinfo->maxpixels = 65536; modeinfo->haveblit = 0; }#endif#if 0 /* Who cares. */ if (cirrus_interlaced(mode)) modeinfo->flags |= IS_INTERLACED;#endif modeinfo->flags &= ~HAVE_RWPAGE; if (modeinfo->bytesperpixel >= 1) { modeinfo->flags |= CAPABLE_LINEAR; if (__svgalib_cirrus_inlinearmode()) modeinfo->flags |= IS_LINEAR; }}/* Read and save chipset-specific registers */static int cirrus_saveregs(unsigned char regs[]){/* int i; *//* #ifdef DEBUG printf("Saving Cirrus extended registers.\n"); #endif */ cirrus_unlock(); /* May be locked again by other programs (e.g. X) */#if 0 /* Save extended CRTC registers. */ for (i = 0; i < 15; i++) { /* was 4 */ port_out(0x18 + i, __svgalib_CRT_I); regs[CIRRUSREG_CR(i)] = port_in(__svgalib_CRT_D); } /* Save extended graphics registers */ for (i = 0; i < 5; i++) { /* was 3 */ port_out(0x09 + i, GRA_I); regs[CIRRUSREG_GR(i)] = port_in(GRA_D); } /* Save extended sequencer registers. */ for (i = 0; i < 27; i++) { port_out(0x05 + i, SEQ_I); regs[CIRRUSREG_SR(i)] = port_in(SEQ_D); }#endif /* Save extended CRTC registers. */ regs[CIRRUSREG_CR(0x19)] = __svgalib_inCR(0x19); regs[CIRRUSREG_CR(0x1A)] = __svgalib_inCR(0x1A); regs[CIRRUSREG_CR(0x1B)] = __svgalib_inCR(0x1B); if (CHIP_HAS_CR1D()) regs[CIRRUSREG_CR(0x1D)] = __svgalib_inCR(0x1D); /* Save extended graphics registers. */ regs[CIRRUSREG_GR(0x09)] = __svgalib_inGR(0x09); regs[CIRRUSREG_GR(0x0A)] = __svgalib_inGR(0x0A); regs[CIRRUSREG_GR(0x0B)] = __svgalib_inGR(0x0B); /* Save extended sequencer registers. */ regs[CIRRUS_SR7] = __svgalib_inSR(0x07); regs[CIRRUS_VCLK3NUMERATOR] = __svgalib_inSR(0x0E); regs[CIRRUS_DRAMCONTROL] = __svgalib_inSR(0x0F); if (CHIP_HAS_PERFTUNINGREGISTER()) regs[CIRRUS_PERFTUNING] = __svgalib_inSR(0x16); if (CHIP_HAS_SR17()) regs[CIRRUS_SR17] = __svgalib_inSR(0x17); regs[CIRRUS_VCLK3DENOMINATOR] = __svgalib_inSR(0x1E); if (CHIP_HAS_MCLK_REGISTER()) regs[CIRRUS_MCLKREGISTER] = __svgalib_inSR(0x1F); /* Save Hicolor DAC register. */ if (CHIP_HAS_HIDDENDAC()) { outb(0x3c6, 0); outb(0x3c6, 0xff); inb(0x3c6); inb(0x3c6); inb(0x3c6); inb(0x3c6); regs[CIRRUSREG_DAC] = inb(0x3c6); } return CIRRUS_TOTAL_REGS - VGA_TOTAL_REGS;}static void writehicolordac(unsigned char c){ outb(0x3c6, 0); outb(0x3c6, 0xff); inb(0x3c6); inb(0x3c6); inb(0x3c6); inb(0x3c6); outb(0x3c6, c); inb(0x3c8);}/* Set chipset-specific registers */static void cirrus_setregs(const unsigned char regs[], int mode){/* #ifdef DEBUG printf("Setting Cirrus extended registers.\n"); #endif */ cirrus_unlock(); /* May be locked again by other programs (eg. X) */ /* Write extended CRTC registers. */ __svgalib_outCR(0x19, regs[CIRRUSREG_CR(0x19)]); __svgalib_outCR(0x1A, regs[CIRRUSREG_CR(0x1A)]); __svgalib_outCR(0x1B, regs[CIRRUSREG_CR(0x1B)]); if (CHIP_HAS_CR1D()) __svgalib_outCR(0x1D, regs[CIRRUSREG_CR(0x1D)]); /* Write extended graphics registers. */ __svgalib_outGR(0x09, regs[CIRRUSREG_GR(0x09)]); __svgalib_outGR(0x0A, regs[CIRRUSREG_GR(0x0A)]); __svgalib_outGR(0x0B, regs[CIRRUSREG_GR(0x0B)]);#ifdef SET_ALL if (CHIP_HAS_GRC_AND_GRD()) { __svgalib_outGR(0x0C, regs[CIRRUSREG_GR(0x0C)]); __svgalib_outGR(0x0D, regs[CIRRUSREG_GR(0x0D)]); } if (CHIP_HAS_GRE()) __svgalib_outGR(0x0E, regs[CIRRUSREG_GR(0x0E)]); if (CHIP_HAS_GR10_AND_GR11()) { __svgalib_outGR(0x10, regs[CIRRUSREG_GR(0x10)]); __svgalib_outGR(0x11, regs[CIRRUSREG_GR(0x11)]); } if (CHIP_HAS_BLT_REGISTERS()) { int i; for (i = 0x20; i <= 0x2A; i++) __svgalib_outGR(i, regs[CIRRUSREG_GR(i)]); for (i = 0x2C; i < 0x2E; i++) __svgalib_outGR(i, regs[CIRRUSREG_GR(i)]); if (CHIP_HAS_BLTWRITEMASK()) __svgalib_outGR(0x2D, regs[CIRRUSREG_GR(0x2D)]); __svgalib_outGR(0x30, regs[CIRRUSREG_GR(0x30)]); __svgalib_outGR(0x32, regs[CIRRUSREG_GR(0x32)]); if (CHIP_HAS_BLTTRANSPARENTCOLOR()) { __svgalib_outGR(0x34, regs[CIRRUSREG_GR(0x34)]); __svgalib_outGR(0x35, regs[CIRRUSREG_GR(0x35)]); __svgalib_outGR(0x38, regs[CIRRUSREG_GR(0x38)]); __svgalib_outGR(0x39, regs[CIRRUSREG_GR(0x39)]); } }#endif /* Write Truecolor DAC register. */ if (CHIP_HAS_HIDDENDAC()) writehicolordac(regs[CIRRUS_HIDDENDAC]); /* Write extended sequencer registers. */ /* Be careful to put the sequencer clocking mode in a safe state. */ __svgalib_outSR(0x07, (regs[CIRRUS_SR7] & ~0x0F) | 0x01); __svgalib_outSR(0x0E, regs[CIRRUS_VCLK3NUMERATOR]); __svgalib_outSR(0x1E, regs[CIRRUS_VCLK3DENOMINATOR]); __svgalib_outSR(0x07, regs[CIRRUS_SR7]); __svgalib_outSR(0x0F, regs[CIRRUS_DRAMCONTROL]); if (CHIP_HAS_PERFTUNINGREGISTER()) __svgalib_outSR(0x16, regs[CIRRUS_PERFTUNING]); if (CHIP_USE_SR17()) __svgalib_outSR(0x17, regs[CIRRUS_SR17]); if (CHIP_HAS_MCLK_REGISTER()) __svgalib_outSR(0x1F, regs[CIRRUS_MCLKREGISTER]);}/* Return nonzero if mode is available */static int cirrus_modeavailable(int mode){ struct info *info; ModeTiming *modetiming; ModeInfo *modeinfo; /* CLGD7548 mode 13 is broken. Remove this if when supported */ if (mode == G320x200x256 && cirrus_chiptype == CLGD7548) return 0; if ((mode < G640x480x256 && mode != G320x200x256) || mode == G720x348x2) return __svgalib_vga_driverspecs.modeavailable(mode); info = &__svgalib_infotable[mode]; if (cirrus_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;}/* Set a mode *//* Local, called by cirrus_setmode(). */static void cirrus_initializemode(unsigned char *moderegs, ModeTiming * modetiming, ModeInfo * modeinfo){ /* Get current values. */ cirrus_saveregs(moderegs); /* Set up the standard VGA registers for a generic SVGA. */ __svgalib_setup_VGA_registers(moderegs, modetiming, modeinfo); /* Set up the extended register values, including modifications */ /* of standard VGA registers. *//* Graphics */ moderegs[CIRRUS_GRAPHICSOFFSET1] = 0; /* Reset banks. */ moderegs[CIRRUS_GRAPHICSOFFSET2] = 0; moderegs[CIRRUS_GRB] = 0; /* 0x01 enables dual banking. */ if (cirrus_memory > 1024) /* Enable 16K granularity. */ moderegs[CIRRUS_GRB] |= 0x20; moderegs[VGA_SR2] = 0xFF; /* Plane mask *//* CRTC */ if (modetiming->VTotal >= 1024 && !(modetiming->flags & INTERLACED)) /* * Double the vertical timing. Used for 1280x1024 NI. * The CrtcVTimings have already been adjusted * by __svgalib_getmodetiming() because of the GREATER_1024_DIVIDE_VERT * flag. */ moderegs[VGA_CR17] |= 0x04; moderegs[CIRRUS_CR1B] = 0x22; if (cirrus_chiptype >= CLGD5434) /* Clear display start bit 19. */ SETBITS(moderegs[CIRRUS_CR1D], 0x80, 0); /* CRTC timing overflows. */ moderegs[CIRRUS_CR1A] = 0; SETBITSFROMVALUE(moderegs[CIRRUS_CR1A], 0xC0, modetiming->CrtcVSyncStart + 1, 0x300); SETBITSFROMVALUE(moderegs[CIRRUS_CR1A], 0x30, modetiming->CrtcHSyncEnd, (0xC0 << 3)); moderegs[CIRRUS_CR19] = 0; /* Interlaced end. */ if (modetiming->flags & INTERLACED) { moderegs[CIRRUS_CR19] = ((modetiming->CrtcHTotal / 8) - 5) / 2; moderegs[CIRRUS_CR1A] |= 0x01;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -