home *** CD-ROM | disk | FTP | other *** search
- /* 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 <string.h> /* for memset */
- #include <sys/mman.h> /* mmap */
- #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"
-
- #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 CHECKCHIP6(c1, c2, c3, c4, c5, c6) ((1 << cirrus_chiptype) & \
- ((1 << c1) | (1 << c2) | (1 << c3) | (1 << c4) | (1 << c5) \
- | (1 << c6)))
- #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 CHECKCHIPGREATEREQUAL(c) (cirrus_chiptype >= c)
- #define CHECKCHIPNOTEQUAL(c) (cirrus_chiptype != c)
-
- #define CHIP_HAS_CR1D() \
- CHECKCHIP3(CLGD5429, CLGD5430, CLGD5434)
- #define CHIP_HAS_GRC_AND_GRD() \
- CHECKCHIP4(CLGD5424, CLGD5426, CLGD5428, CLGD5429)
- #define CHIP_HAS_GRE() \
- CHECKCHIP4(CLGD5428, CLGD5429, CLGD5430, CLGD5434)
- #define CHIP_HAS_GR10_AND_GR11() \
- CHECKCHIP6(CLGD5424, CLGD5426, CLGD5428, CLGD5429, CLGD5430, CLGD5434)
- #define CHIP_HAS_BLTTRANSPARENTCOLOR() \
- CHECKCHIP2(CLGD5426, CLGD5428)
- #define CHIP_HAS_PERFTUNINGREGISTER() \
- CHECKCHIP6(CLGD5424, CLGD5426, CLGD5428, CLGD5429, CLGD5430, CLGD5434)
- #define CHIP_HAS_MCLK_REGISTER() \
- CHECKCHIP8(CLGD5420B, CLGD5422C, CLGD5424, CLGD5426, CLGD5428, \
- CLGD5429, CLGD5430, CLGD5434)
- #define CHIP_HAS_32BIT_DRAM_BUS() \
- CHECKCHIPGREATEREQUAL(CLGD5420B)
- #define CHIP_HAS_64BIT_DRAM_BUS() \
- CHECKCHIP1(CLGD5434)
- #define CHIP_HAS_HIDDENDAC() \
- CHECKCHIPGREATEREQUAL(CLGD5420B)
- #define CHIP_HAS_ACCELERATION() \
- CHECKCHIPNOTEQUAL(CLGD5420B)
- #define CHIP_HAS_SR17() \
- CHECKCHIPGREATEREQUAL(CLGD5422)
-
-
- /* 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();
-
- static int cirrus_memory;
- static int cirrus_chiptype;
- static int cirrus_chiprev;
- static unsigned char actualMCLK, programmedMCLK;
- static int DRAMbandwidth, DRAMbandwidthLimit;
- static unsigned char *mmio_base;
-
-
- static CardSpecs *cardspecs;
-
- #define NU_FIXED_CLOCKS 19
-
- /* 12.588 clock (0x33, 0x3B) replaced with 12.599 (0x2C, 0x33). */
-
- static int cirrus_fixed_clocks[NU_FIXED_CLOCKS] = {
- 12599, 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, 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, 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, CLGD5420B, CLGD5422, CLGD5422C, CLGD5424, CLGD5426,
- CLGD5428, CLGD5429, CLGD5430, CLGD5434};
-
-
- int cirrus_inlinearmode() {
- outb(0x3c4, 0x07);
- return (inb(0x3c5) & 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;
- if (modeinfo->bytesperpixel == 1 &&
- cirrus_chiptype >= CLGD5426 &&
- (VMEM == -1 ? modeinfo->linewidth * modeinfo->height :
- VMEM) <= (cirrus_memory * 1024 - 64)
- && modeinfo->bytesperpixel == 1) {
- #if 0 /* Fix in the next release (disabled in 1.21) */
- modeinfo->haveblit = HAVE_FILLBLIT | HAVE_BITBLIT |
- HAVE_IMAGEBLIT;
- #else
- modeinfo->haveblit = HAVE_FILLBLIT;
- #endif
- /* 64 bytes are used a fill pattern */
- modeinfo->maxpixels = (cirrus_memory * 1024 - 64)
- / modeinfo->bytesperpixel;
- }
- else
- 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 (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, CRT_I);
- regs[CIRRUSREG_CR(i)] = port_in(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)] = inCR(0x19);
- regs[CIRRUSREG_CR(0x1A)] = inCR(0x1A);
- regs[CIRRUSREG_CR(0x1B)] = inCR(0x1B);
- if (CHIP_HAS_CR1D())
- regs[CIRRUSREG_CR(0x1D)] = inCR(0x1D);
-
- /* Save extended graphics registers. */
- regs[CIRRUSREG_GR(0x09)] = inGR(0x09);
- regs[CIRRUSREG_GR(0x0A)] = inGR(0x0A);
- regs[CIRRUSREG_GR(0x0B)] = inGR(0x0B);
-
- /* Save extended sequencer registers. */
- regs[CIRRUS_SR7] = inSR(0x07);
- regs[CIRRUS_VCLK3NUMERATOR] = inSR(0x0E);
- regs[CIRRUS_DRAMCONTROL] = inSR(0x0F);
- if (CHIP_HAS_PERFTUNINGREGISTER())
- regs[CIRRUS_PERFTUNING] = inSR(0x16);
- if (CHIP_HAS_SR17())
- regs[CIRRUS_SR17] = inSR(0x17);
- regs[CIRRUS_VCLK3DENOMINATOR] = inSR(0x1E);
- if (CHIP_HAS_MCLK_REGISTER())
- regs[CIRRUS_MCLKREGISTER] = 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 )
- {
- int i;
-
- /* #ifdef DEBUG
- printf("Setting Cirrus extended registers.\n");
- #endif
- */
- cirrus_unlock(); /* May be locked again by other programs (eg. X) */
-
- /* Write extended CRTC registers. */
- outCR(0x19, regs[CIRRUSREG_CR(0x19)]);
- outCR(0x1A, regs[CIRRUSREG_CR(0x1A)]);
- outCR(0x1B, regs[CIRRUSREG_CR(0x1B)]);
- if (CHIP_HAS_CR1D())
- outCR(0x1D, regs[CIRRUSREG_CR(0x1D)]);
-
- /* Write extended graphics registers. */
- outGR(0x09, regs[CIRRUSREG_GR(0x09)]);
- outGR(0x0A, regs[CIRRUSREG_GR(0x0A)]);
- outGR(0x0B, regs[CIRRUSREG_GR(0x0B)]);
- #ifdef SET_ALL
- if (CHIP_HAS_GRC_AND_GRD()) {
- outGR(0x0C, regs[CIRRUSREG_GR(0x0C)]);
- outGR(0x0D, regs[CIRRUSREG_GR(0x0D)]);
- }
- if (CHIP_HAS_GRE())
- outGR(0x0E, regs[CIRRUSREG_GR(0x0E)];
- if (CHIP_HAS_GR10_AND_GR11() {
- outGR(0x10, regs[CIRRUSREG_GR(0x10)]);
- outGR(0x11, regs[CIRRUSREG_GR(0x11)]);
- }
- if (CHIP_HAS_BLT_REGISTERS()) {
- for (i = 0x20; i <= 0x2A; i++)
- outGR(i, regs[CIRRUSREG_GR(i)]);
- for (i = 0x2C; i < 0x2E; i++)
- outGR(i, regs[CIRRUSREG_GR(i)]);
- if (CHIP_HAS_BLTWRITEMASK())
- outGR(0x2D, regs[CIRRUSREG_GR(0x2D));
- outGR(0x30, regs[CIRRUSREG_GR(0x30));
- outGR(0x32, regs[CIRRUSREG_GR(0x32));
- if (CHIP_HAS_BLTTRANSPARENTCOLOR()) {
- outGR(0x34, regs[CIRRUSREG_GR(0x34));
- outGR(0x35, regs[CIRRUSREG_GR(0x35));
- outGR(0x38, regs[CIRRUSREG_GR(0x38));
- 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. */
- outSR(0x07, (regs[CIRRUS_SR7] & ~0x0F) | 0x01);
-
- outSR(0x0E, regs[CIRRUS_VCLK3NUMERATOR]);
- outSR(0x1E, regs[CIRRUS_VCLK3DENOMINATOR]);
- outSR(0x07, regs[CIRRUS_SR7]);
- outSR(0x0F, regs[CIRRUS_DRAMCONTROL]);
- if (CHIP_HAS_PERFTUNINGREGISTER())
- outSR(0x16, regs[CIRRUS_PERFTUNING]);
- if (CHIP_HAS_SR17())
- outSR(0x17, regs[CIRRUS_SR17]);
- if (CHIP_HAS_MCLK_REGISTER())
- outSR(0x1F, regs[CIRRUS_MCLKREGISTER]);
- }
-
-
- /* Return nonzero if mode is available */
-
- static int cirrus_modeavailable( int mode ) {
- struct info *info;
- ModeTiming *modetiming;
- ModeInfo *modeinfo;
-
- if ((mode < G640x480x256 && mode != G320x200x256)
- || mode == G720x348x2)
- return vga_driverspecs.modeavailable(mode);
-
- info = &__svgalib_infotable[mode];
- if (cirrus_memory * 1024 < info->ydim * info->xbytes)
- return 0;
-
- modeinfo = createModeInfoStructureForSvgalibMode(mode);
-
- modetiming = malloc(sizeof(ModeTiming));
- if (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. */
- 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 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;
- }
-
- /* Scanline offset */
- if (modeinfo->bytesPerPixel == 4) {
- /* At 32bpp the chip does an extra multiplication by two. */
- moderegs[VGA_SCANLINEOFFSET] = modeinfo->lineWidth >> 4;
- SETBITSFROMVALUE(moderegs[CIRRUS_CR1B], 0x10,
- modeinfo->lineWidth, 0x1000);
- }
- else
- if (modeinfo->bitsPerPixel == 4)
- /* 16 color mode (planar). */
- moderegs[VGA_SCANLINEOFFSET] = modeinfo->lineWidth >> 1;
- else {
- moderegs[VGA_SCANLINEOFFSET] = modeinfo->lineWidth >> 3;
- SETBITSFROMVALUE(moderegs[CIRRUS_CR1B], 0x10,
- modeinfo->lineWidth, 0x800);
- }
-
- /* Clocking */
- moderegs[VGA_MISCOUTPUT] |= 0x0C; /* Use VCLK3. */
- moderegs[CIRRUS_VCLK3NUMERATOR] =
- fixed_clock_numerator[modetiming->selectedClockNo];
- moderegs[CIRRUS_VCLK3DENOMINATOR] =
- fixed_clock_denominator[modetiming->selectedClockNo];
-
- /* DAC register and Sequencer Mode */
- {
- unsigned char DAC, SR7;
- DAC = 0x00;
- SR7 = 0x00;
- if (modeinfo->bytesPerPixel > 0)
- SR7 = 0x01; /* Packed-pixel mode. */
- if (modeinfo->bytesPerPixel == 2) {
- int rgbmode;
- rgbmode = 0; /* 5-5-5 RGB. */
- if (modeinfo->colorBits == 16)
- rgbmode = 1; /* Add one for 5-6-5 RGB. */
- if (cirrus_chiptype >= CLGD5426) {
- /* Pixel clock (double edge) mode. */
- DAC = 0xD0 + rgbmode;
- SR7 = 0x07;
- }
- else {
- /* Single-edge (double VCLK). */
- DAC = 0xF0 + rgbmode;
- SR7 = 0x03;
- }
- }
- if (modeinfo->bytesPerPixel >= 3) {
- /* Set 8-8-8 RGB mode. */
- DAC = 0xE5;
- SR7 = 0x05;
- if (modeinfo->bytesPerPixel == 4)
- SR7 = 0x09;
- }
- #ifdef SUPPORT_5434_PALETTE_CLOCK_DOUBLING
- if (modeinfo->bytesPerPixel == 1 && (modetiming->flags & HADJUSTED)) {
- /* Palette clock doubling mode on 5434 8bpp. */
- DAC = 0x4A;
- SR7 = 0x07;
- }
- #endif
- moderegs[CIRRUS_HIDDENDAC] = DAC;
- moderegs[CIRRUS_SR7] = SR7;
- }
-
- /* DRAM control and CRT FIFO */
- if (cirrus_chiptype >= CLGD5422)
- /* Enable large CRT FIFO. */
- moderegs[CIRRUS_DRAMCONTROL] |= 0x20;
- if (cirrus_memory == 2048 && cirrus_chiptype <= CLGD5429)
- /* Enable DRAM Bank Select. */
- moderegs[CIRRUS_DRAMCONTROL] |= 0x80;
- if (cirrus_chiptype >= CLGD5422) {
- /* CRT FIFO threshold setting. */
- unsigned char threshold;
- threshold = 8;
- if (cirrus_chiptype == CLGD5434)
- threshold = 1;
- /* XXX Needs more elaborate setting. */
- SETBITS(moderegs[CIRRUS_PERFTUNING], 0x0F, threshold);
- }
- if (CHIP_HAS_MCLK_REGISTER())
- if (programmedMCLK != actualMCLK
- && modeinfo->bytesPerPixel > 0)
- /* Program higher MCLK for packed-pixel modes. */
- moderegs[CIRRUS_MCLKREGISTER] = programmedMCLK;
- }
-
-
- /* This is the clock mapping function that is put in the CardSpecs. */
-
- static int cirrus_map_clock( int bpp, int pixelclock ) {
- if (bpp == 24)
- /* All chips need a tripled clock for 24bpp. */
- return pixelclock * 3;
- if (bpp == 16 && cirrus_chiptype <= CLGD5424)
- /* The 5422/24 need to use a doubled clock. */
- return pixelclock * 2;
- return pixelclock;
- }
-
- /* This is the horizontal CRTC mapping function in the CardSpecs. */
-
- static int cirrus_map_horizontal_crtc( int bpp, int pixelclock, int htiming ) {
- #ifdef ALWAYS_USE_5434_PALETTE_CLOCK_DOUBLING
- if (bpp == 8 && cirrus_chiptype == CLGD5434)
- #else
- if (bpp == 8 && cirrus_chiptype == CLGD5434 && pixelclock > 86000)
- #endif
- /* 5434 palette clock doubling mode; divide CRTC by 2. */
- return htiming / 2;
- /* Otherwise, don't change. */
- return htiming;
- }
-
- static void init_acceleration_specs_for_mode( AccelSpecs *accelspecs, int bpp,
- int width_in_pixels );
-
- static int cirrus_setmode( int mode, int prv_mode ) {
- unsigned char *moderegs;
- ModeTiming *modetiming;
- ModeInfo *modeinfo;
-
- if ((mode < G640x480x256 && mode != G320x200x256)
- || mode == G720x348x2) {
- clear_accelspecs(driverspecs->accelspecs);
- /* Let the standard VGA driver set standard VGA modes */
- /* But first reset an Cirrus extended register that */
- /* an old XFree86 Trident probe corrupts. */
- outw(0x3d4, 0x4a0b);
- return vga_driverspecs.setmode(mode);
- }
- if (!cirrus_modeavailable(mode))
- return 1;
-
- modeinfo = createModeInfoStructureForSvgalibMode(mode);
-
- modetiming = malloc(sizeof(ModeTiming));
- if (getmodetiming(modetiming, modeinfo, cardspecs)) {
- free(modetiming);
- free(modeinfo);
- return 1;
- }
-
- moderegs = malloc(CIRRUS_TOTAL_REGS);
-
- cirrus_initializemode(moderegs, modetiming, modeinfo);
- free(modetiming);
-
- __vga_setregs(moderegs); /* Set standard regs. */
- cirrus_setregs(moderegs, mode); /* Set extended regs. */
- free(moderegs);
-
- InitializeAcceleratorInterface(modeinfo);
-
- init_acceleration_specs_for_mode(driverspecs->accelspecs,
- modeinfo->bitsPerPixel,
- modeinfo->lineWidth / modeinfo->bytesPerPixel);
-
- cirrusaccel_init(driverspecs->accelspecs,
- modeinfo->bitsPerPixel,
- modeinfo->lineWidth / modeinfo->bytesPerPixel);
-
- free(modeinfo);
- return 0;
- }
-
-
- /* Unlock chipset-specific registers */
-
- static void cirrus_unlock() {
- int vgaIOBase, temp;
-
- /* Are we Mono or Color? */
- vgaIOBase = (inb(0x3CC) & 0x01) ? 0x3D0 : 0x3B0;
-
- outb(0x3C4,0x06);
- outb(0x3C5,0x12); /* unlock cirrus special */
-
- /* Put the Vert. Retrace End Reg in temp */
-
- outb(vgaIOBase + 4, 0x11); temp = inb(vgaIOBase + 5);
-
- /* Put it back with PR bit set to 0 */
- /* This unprotects the 0-7 CRTC regs so */
- /* they can be modified, i.e. we can set */
- /* the timing. */
-
- outb(vgaIOBase + 5, temp & 0x7F);
- }
-
-
- /* Relock chipset-specific registers */
- /* (currently not used) */
-
- static void cirrus_lock() {
- outb(0x3C4,0x06);
- outb(0x3C5,0x0F); /* relock cirrus special */
- }
-
-
- /* Indentify chipset, initialize and return non-zero if detected */
-
- static int cirrus_test() {
- int oldlockreg;
- int lockreg;
-
- outb(0x3c4, 0x06);
- oldlockreg = inb(0x3c5);
-
- cirrus_unlock();
-
- /* If it's a Cirrus at all, we should be */
- /* able to read back the lock register */
-
- outb(0x3C4,0x06);
- lockreg = inb(0x3C5);
-
- /* Ok, if it's not 0x12, we're not a Cirrus542X. */
- if (lockreg != 0x12) {
- outb(0x3c4, 0x06);
- outb(0x3c5, oldlockreg);
- return 0;
- }
-
- /* The above check seems to be weak, so we also check the chip ID. */
-
- outb(CRT_I, 0x27);
- switch (inb(CRT_D) >> 2) {
- case 0x22 :
- case 0x23 :
- case 0x24 :
- case 0x25 :
- case 0x26 :
- case 0x27 : /* 5429 */
- case 0x28 : /* 5430 */
- case 0x2A : /* 5434 */
- break;
- default :
- outb(0x3c4, 0x06);
- outb(0x3c5, oldlockreg);
- return 0;
- }
-
- if (cirrus_init(0, 0, 0))
- return 0; /* failure */
- return 1;
- }
-
-
- /* Bank switching function -- set 64K page number */
-
- static void cirrus_setpage_2M( unsigned page ) {
- /* Cirrus banking register has been set to 16K granularity */
- outw(0x3ce, (page << 10) + 0x09);
- }
-
- static void cirrus_setpage( unsigned page ) {
- /* default 4K granularity */
- outw(0x3ce, (page << 12) + 0x09);
- }
-
-
- /* No r/w paging */
- static void cirrus_setrdpage(unsigned page) { }
- static void cirrus_setwrpage(unsigned page) { }
-
-
- /* Set display start address (not for 16 color modes) */
- /* Cirrus supports any address in video memory (up to 2Mb) */
-
- static void cirrus_setdisplaystart( int address ) {
- outw(0x3d4, 0x0d + ((address >> 2) & 0x00ff) * 256); /* sa2-sa9 */
- outw(0x3d4, 0x0c + ((address >> 2) & 0xff00)); /* sa10-sa17 */
- inb(0x3da); /* set ATC to addressing mode */
- outb(0x3c0, 0x13 + 0x20); /* select ATC reg 0x13 */
- /* Cirrus specific bits 0,1 and 18,19,20: */
- outb(0x3c0, (inb(0x3c1) & 0xf0) | (address & 3));
- /* write sa0-1 to bits 0-1; other cards use bits 1-2 */
- outb(0x3d4, 0x1b);
- outb(0x3d5, (inb(0x3d5) & 0xf2)
- | ((address & 0x40000) >> 18) /* sa18: write to bit 0 */
- | ((address & 0x80000) >> 17) /* sa19: write to bit 2 */
- | ((address & 0x100000) >> 17)); /* sa20: write to bit 3 */
- outb(0x3d4, 0x1d);
- if (cirrus_memory > 2048)
- outb(0x3d5, (inb(0x3d5) & 0x7f)
- | ((address & 0x200000) >> 14)); /* sa21: write to bit 7 */
- }
-
-
- /* Set logical scanline length (usually multiple of 8) */
- /* Cirrus supports multiples of 8, up to 4088 */
-
- static void cirrus_setlogicalwidth( int width ) {
- outw(0x3d4, 0x13 + (width >> 3) * 256); /* lw3-lw11 */
- outb(0x3d4, 0x1b);
- outb(0x3d5, (inb(0x3d5) & 0xef) | ((width & 0x800) >> 7));
- /* write lw12 to bit 4 of Sequencer reg. 0x1b */
- }
-
- static void cirrus_setlinear(int addr)
- {
- int val;
- outb(0x3c4, 0x07);
- val = inb(0x3c5);
- outb(0x3c5, (val & 0x0f) | (addr << 4));
- }
-
- static int cirrus_linear( int op, int param ) {
- if (op == LINEAR_ENABLE) {
- cirrus_setlinear(0xE);
- return 0;
- }
- if (op == LINEAR_DISABLE) {
- cirrus_setlinear(0);
- return 0;
- }
- if (cirrus_chiptype >= CLGD5424 && cirrus_chiptype <= CLGD5429) {
- if (op == LINEAR_QUERY_BASE) {
- if (param == 0)
- return 0xE00000; /* 14MB */
- /*
- * Trying 64MB on a system with 16MB of memory is unsafe if the
- * card maps at 14MB. 14 MB was not attempted because of the
- * system memory check in vga_setlinearaddressing(). However,
- * linear addressing is enabled when looking at 64MB, causing a
- * clash between video card and system memory at 14MB.
- */
- if (__svgalib_physmem() <= 13 * 1024 * 1024) {
- if (param == 1)
- return 0x4000000; /* 64MB */
- if (param == 2)
- return 0x4E00000; /* 78MB */
- if (param == 3)
- return 0x2000000; /* 32MB */
- }
- return -1;
- }
- }
- if (cirrus_chiptype >= CLGD5430) {
- if (op == LINEAR_QUERY_BASE) {
- if (param == 0)
- return 0x04000000; /* 64MB */
- if (param == 1)
- return 0x80000000; /* 2048MB */
- if (param == 2)
- return 0x02000000; /* 32MB */
- if (param == 3)
- return 0x08000000; /* 128MB */
- /* While we're busy, try some common PCI */
- /* motherboard-configured addresses as well. */
- /* We only read, so should be safe. */
- if (param == 4)
- return 0xA0000000;
- if (param == 5)
- return 0xA8000000;
- if (param == 6)
- return 0xF0000000;
- return -1;
- }
- }
-
- if (op == LINEAR_QUERY_RANGE || op == LINEAR_QUERY_GRANULARITY)
- return 0; /* No granularity or range. */
- else
- return -1; /* Unknown function. */
- }
-
-
- /* Function table (exported) */
-
- static int cirrus_bitblt( int, int, int, int, int );
- static int cirrus_imageblt( unsigned *, int, int, int, int );
- static int cirrus_fillblt( int, int, int, int, int );
- static int cirrus_hlinelistblt( int, int, int *, int *, int, int );
- static int cirrus_bltwait();
-
- DriverSpecs cirrus_driverspecs = {
- cirrus_saveregs,
- cirrus_setregs,
- cirrus_unlock,
- cirrus_lock,
- cirrus_test,
- cirrus_init,
- cirrus_setpage,
- cirrus_setrdpage,
- cirrus_setwrpage,
- cirrus_setmode,
- cirrus_modeavailable,
- cirrus_setdisplaystart,
- cirrus_setlogicalwidth,
- cirrus_getmodeinfo,
- cirrus_bitblt,
- cirrus_imageblt,
- cirrus_fillblt,
- cirrus_hlinelistblt,
- cirrus_bltwait,
- 0, /* ext_set */
- 0, /* accel */
- cirrus_linear,
- 0 /* accelspecs, filled in during init. */
- };
-
-
- /* Initialize chipset (called after detection) */
-
- static char *cirrus_chipname[] = {
- "5420", "5420-75QC-B", "5422", "5422-80QC-C", "5424", "5426", "5428",
- "5429", "5430", "5434"
- };
-
- static int cirrus_init( int force, int par1, int par2 ) {
- unsigned char v;
- cirrus_unlock();
- if (force) {
- cirrus_memory = par1;
- cirrus_chiptype = par2;
- }
- else {
- unsigned char partstatus;
- outb(CRT_I, 0x27);
- cirrus_chiptype = inb(CRT_D) >> 2;
- cirrus_chiprev = 0;
- partstatus = inCR(0x25);
- switch (cirrus_chiptype) {
- case 0x22 :
- cirrus_chiptype = CLGD5420;
- #if 0
- /* Check for CL-GD5420-75QC-B. */
- /* It has a Hidden-DAC register. */
- outb(0x3C6, 0x00);
- outb(0x3C6, 0xFF);
- inb(0x3C6); inb(0x3c6); inb(0x3C6); inb(0x3C6);
- if (inb(0x3C6) != 0xFF)
- cirrus_chiptype = CLGD5420B; break;
- break;
- #endif
- case 0x23 : cirrus_chiptype = CLGD5422; break;
- case 0x24 : cirrus_chiptype = CLGD5426; break;
- case 0x25 :
- cirrus_chiptype = CLGD5424;
- /*
- * Some CL-GD5422's ID as CL-GD5424.
- * Check for writability of GRC.
- */
- v = inGR(0x0C);
- outGR(0x0C, 0x55);
- if (inGR(0x0C) != 0x55)
- cirrus_chiptype = CLGD5422;
- outGR(0x0C, v);
- break;
- case 0x26 : cirrus_chiptype = CLGD5428; break;
- case 0x27 : cirrus_chiptype = CLGD5429; break;
- case 0x28 : cirrus_chiptype = CLGD5430; break;
- case 0x2A :
- cirrus_chiptype = CLGD5434;
- if ((partstatus & 0xC0) == 0xC0)
- /* Rev. E, can do 60 MHz MCLK. */
- cirrus_chiprev = 1;
- break;
- default :
- printf("Unknown Cirrus chip %2x.\n",
- cirrus_chiptype);
- return -1;
- }
-
- #if 0
- if (cirrus_chiptype == CLGD5422) {
- /* Rev. C has programmable MCLK register; */
- /* check for it. */
- /* This check is wrong. */
- if (inSR(0x1F) != 0xFF)
- cirrus_chiptype = CLGD5422C;
- }
- #endif
-
- /* Now determine the amount of memory. */
- outb(0x3c4, 0x0a); /* read memory register */
- /* This depends on the BIOS having set a scratch register. */
- v = inb(0x3c5);
- cirrus_memory = 256 << ((v >> 3) & 3);
-
- /* Determine memory the correct way for the 543x, and
- * for the 542x if the amount seems incorrect. */
- if (cirrus_chiptype >= CLGD5430 || (cirrus_memory <= 256
- && cirrus_chiptype != CLGD5420)) {
- unsigned char SRF;
- cirrus_memory = 512;
- outb(0x3c4, 0x0f);
- SRF = inb(0x3c5);
- if (SRF & 0x10)
- /* 32-bit DRAM bus. */
- cirrus_memory *= 2;
- if ((SRF & 0x18) == 0x18)
- /* 64-bit DRAM data bus width; assume 2MB. */
- /* Also indicates 2MB memory on the 5430. */
- cirrus_memory *= 2;
- if (cirrus_chiptype != CLGD5430 && (SRF & 0x80))
- /* If DRAM bank switching is enabled, there */
- /* must be twice as much memory installed. */
- /* (4MB on the 5434) */
- cirrus_memory *= 2;
- }
- }
- if (__svgalib_driver_report) {
- printf("Using Cirrus Logic GD542x/3x driver (%s, %dK).\n",
- cirrus_chipname[cirrus_chiptype], cirrus_memory);
- }
-
- if (CHIP_HAS_MCLK_REGISTER())
- actualMCLK = inSR(0x1F) & 0x3F;
- else {
- static unsigned char fixedMCLK[4] = { 0x1c, 0x19, 0x17, 0x15 };
- actualMCLK = fixedMCLK[inSR(0x0F) & 3];
- }
- programmedMCLK = actualMCLK;
- if (cirrus_chiptype == CLGD5434 && cirrus_chiprev > 0)
- /* 5434 rev. E+ supports 60 MHz in graphics modes. */
- programmedMCLK = 0x22;
- DRAMbandwidth = 14318 * (int)programmedMCLK / 16;
- if (cirrus_memory >= 512)
- /* At least 16-bit DRAM bus. */
- DRAMbandwidth *= 2;
- if (cirrus_memory >= 1024 && CHIP_HAS_32BIT_DRAM_BUS())
- /* At least 32-bit DRAM bus. */
- DRAMbandwidth *= 2;
- if (cirrus_memory >= 2048 && CHIP_HAS_64BIT_DRAM_BUS())
- /* 64-bit DRAM bus. */
- DRAMbandwidth *= 2;
- /*
- * Calculate highest acceptable DRAM bandwidth to be taken up
- * by screen refresh. Satisfies
- * total bandwidth >= refresh bandwidth * 1.1
- */
- DRAMbandwidthLimit = (DRAMbandwidth * 10) / 11;
-
- /* begin: Initialize card specs. */
- cardspecs = malloc(sizeof(CardSpecs));
- cardspecs->videoMemory = cirrus_memory;
- /*
- * First determine clock limits for the chip (DAC), then
- * adjust them according to the available DRAM bandwidth.
- * For 32-bit DRAM cards the 16bpp clock limit is initially
- * set very high, but they are cut down by the DRAM bandwidth
- * check.
- */
- cardspecs->maxPixelClock4bpp = 75000; /* 5420 */
- cardspecs->maxPixelClock8bpp = 45000; /* 5420 */
- cardspecs->maxPixelClock16bpp = 0; /* 5420 */
- cardspecs->maxPixelClock24bpp = 0;
- cardspecs->maxPixelClock32bpp = 0;
- if (cirrus_chiptype == CLGD5420B) {
- /*
- * CL-GD5420-75QC-B
- * Deviating chip, may be used in cheap ISA cards.
- * 32-bit DRAM bus and Truecolor DAC but cannot do
- * LUT > 45 MHz, and has no (less?) acceleration.
- */
- cardspecs->maxPixelClock16bpp = 75000 / 2;
- cardspecs->maxPixelClock24bpp = 25175;
- }
- if (cirrus_chiptype >= CLGD5422) {
- /* 5422/24/26/28 have VCLK spec of 80 MHz. */
- cardspecs->maxPixelClock4bpp = 80000;
- cardspecs->maxPixelClock8bpp = 80000;
- if (cirrus_chiptype >= CLGD5426)
- /* DRAM bandwidth will be limiting factor. */
- cardspecs->maxPixelClock16bpp = 80000;
- else
- /* Clock / 2 16bpp requires 32-bit DRAM bus. */
- if (cirrus_memory >= 1024)
- cardspecs->maxPixelClock16bpp = 80000 / 2;
- /* Clock / 3 24bpp requires 32-bit DRAM bus. */
- if (cirrus_memory >= 1024)
- cardspecs->maxPixelClock24bpp = 80000 / 3;
- }
- if (cirrus_chiptype >= CLGD5429) {
- /* 5429, 5430, 5434 have VCLK spec of 86 MHz. */
- cardspecs->maxPixelClock4bpp = 86000;
- cardspecs->maxPixelClock8bpp = 86000;
- cardspecs->maxPixelClock16bpp = 86000;
- if (cirrus_memory >= 1024)
- cardspecs->maxPixelClock24bpp = 86000 / 3;
- }
- if (cirrus_chiptype >= CLGD5434) {
- #ifdef SUPPORT_5434_PALETTE_CLOCK_DOUBLING
- cardspecs->maxPixelClock8bpp = 108300;
- #endif
- if (cirrus_memory >= 2048)
- /* 32bpp requires 64-bit DRAM bus. */
- cardspecs->maxPixelClock32bpp = 86000;
- }
- cardspecs->maxPixelClock8bpp = min(cardspecs->maxPixelClock8bpp,
- DRAMbandwidthLimit);
- cardspecs->maxPixelClock16bpp = min(cardspecs->maxPixelClock16bpp,
- DRAMbandwidthLimit / 2);
- cardspecs->maxPixelClock24bpp = min(cardspecs->maxPixelClock24bpp,
- DRAMbandwidthLimit / 3);
- cardspecs->maxPixelClock32bpp = min(cardspecs->maxPixelClock32bpp,
- DRAMbandwidthLimit / 4);
- cardspecs->flags = INTERLACE_DIVIDE_VERT | GREATER_1024_DIVIDE_VERT;
- /* Initialize clocks (only fixed set for now). */
- cardspecs->nClocks = NU_FIXED_CLOCKS;
- cardspecs->clocks = cirrus_fixed_clocks;
- cardspecs->mapClock = cirrus_map_clock;
- cardspecs->mapHorizontalCrtc = cirrus_map_horizontal_crtc;
- cardspecs->maxHorizontalCrtc = 2040;
- /* Disable 16-color SVGA modes (don't work correctly). */
- cardspecs->maxPixelClock4bpp = 0;
- /* end: Initialize card specs. */
-
- #if 0
- /* begin: Initialize driver options. */
- register_option(5434_VLB_ZERO_WAITSTATE);
- register_option(50MHZ_MCLK);
- register_option(55MHZ_MCLK);
- register_option(60MHZ_MCLK);
- register_option(542X_VLB_NORMAL_WAITSTATES);
- register_option(CRT_FIFO_CONSERVATIVE);
- register_option(CRT_FIFO_AGGRESSIVE);
- register_option(NO_ACCELERATION);
- register_option(NO_MMIO);
- /* end: Initialize driver options. */
- #endif
-
- /* Initialize accelspecs structure. */
- cirrus_driverspecs.accelspecs = malloc(sizeof(AccelSpecs));
- cirrus_driverspecs.accelspecs->flags = ACCELERATE_ANY_LINEWIDTH;
- if (cirrus_chiptype >= CLGD5429) {
- /* Map memory-mapped I/O register space. */
- mmio_base = valloc(32 * 1024);
- mmap(mmio_base, 32 * 1024, PROT_WRITE, MAP_FIXED | MAP_SHARED,
- __svgalib_mem_fd, 0xB8000);
- }
-
- /* Set up the correct paging routine */
- if (cirrus_memory >= 2048)
- cirrus_driverspecs.setpage =
- cirrus_setpage_2M;
-
- driverspecs = &cirrus_driverspecs;
-
- return 0;
- }
-
-
-
- /* Some information on the accelerated features of the 5426,
- derived from the Databook.
-
- port index
-
- Addresses have 21 bits (2Mb of memory).
- 0x3ce, 0x28 bits 0-7 of the destination address
- 0x3ce, 0x29 bits 8-15
- 0x3ce, 0x2a bits 16-20
-
- 0x3ce, 0x2c bits 0-7 of the source address
- 0x3ce, 0x2d bits 8-15
- 0x3ce, 0x2e bits 16-20
-
- Maximum pitch is 4095.
- 0x3ce, 0x24 bits 0-7 of the destination pitch (screen width)
- 0x3ce, 0x25 bits 8-11
-
- 0x3ce, 0x26 bits 0-7 of the source pitch (screen width)
- 0x3ce, 0x27 bits 8-11
-
- Maximum width is 2047.
- 0x3ce, 0x20 bits 0-7 of the box width - 1
- 0x3ce, 0x21 bits 8-10
-
- Maximum height is 1023.
- 0x3ce, 0x22 bits 0-7 of the box height - 1
- 0x3ce, 0x23 bits 8-9
-
- 0x3ce, 0x30 BLT mode
- bit 0: direction (0 = down, 1 = up)
- bit 1: destination
- bit 2: source (0 = video memory, 1 = system memory)
- bit 3: enable transparency compare
- bit 4: 16-bit color expand/transparency
- bit 6: 8x8 pattern copy
- bit 7: enable color expand
-
- 0x31 BLT status
- bit 0: busy
- bit 1: start operation (1)/suspend (0)
- bit 2: reset
- bit 3: set while blit busy/suspended
-
- 0x32 BLT raster operation
- 0x00 black
- 0x01 white
- 0x0d copy source
- 0xd0 copy inverted source
- 0x0b invert destination
- 0x05 logical AND
- 0x6d logical OR (paint)
- 0x59 XOR
-
- 0x34 BLT transparent color
- 0x35 high byte
-
- 0x3ce, 0x00 background color (for color expansion)
- 0x3ce, 0x01 foreground color
- 0x3ce, 0x10 high byte of background color for 16-bit pixels
- 0x3ce, 0x11 high byte of foreground color
-
- 0x3ce, 0x0b bit 1: enable BY8 addressing
- 0x3c4, 0x02 8-bit plane mask for BY8 (corresponds to 8 pixels)
- (write mode 1, 4, 5)
- 0x3c5, 0x05 bits 0-2: VGA write mode
- extended write mode 4: write up to 8 pixels in
- foreground color (BY8)
- extended write mode 5: write 8 pixels in foreground/
- background color (BY8)
- This may also work in normal non-BY8 packed-pixel mode.
-
- When doing blits from system memory to video memory, pixel data
- can apparently be written to any video address in 16-bit words, with
- the each scanline padded to 4-byte alignment. This is handy because
- the chip handles line transitions and alignment automatically (and
- can do, for example, masking).
-
- The pattern copy requires an 8x8 pattern (64 pixels) at the source
- address in video memory, and fills a box with specified size and
- destination address with the pattern. This is in fact the way to do
- solid fills.
-
- mode pattern
- Color Expansion 8 bytes (monochrome bitmap)
- 8-bit pixels 64 bytes
- 16-bit pixels 128 bytes
-
- */
-
-
- static int cirrus_bltwait() {
- outb(0x3ce, 0x31);
- while (inb(0x3cf) & 1); /* wait until finished */
- return 0;
- }
-
- static int cirrus_bitblt( int srcaddr, int destaddr, int w, int h,
- int pitch ) {
- int blt_direction = 0x0000;
-
- w--;
- h--;
-
- /*
- if the blit goes downwards, we have to start from lower right
- corner instead of upper left corner to cope with overlapping regions
- */
-
- if (destaddr > srcaddr) {
- srcaddr += h*pitch + w;
- destaddr += h*pitch + w;
- blt_direction = 0x0100;
- }
-
- outw(0x3ce, 0x20 + (w << 8)); /* bits 0-7 of width */
- outw(0x3ce, 0x21 + (w & 0xff00)); /* bits 8-10 */
-
- outw(0x3ce, 0x22 + (h << 8)); /* bits 0-7 of height */
- outw(0x3ce, 0x23 + (h & 0xff00)); /* bits 8-9 */
-
- outw(0x3ce, 0x24 + (pitch << 8)); /* bits 0-7 of dest. pitch */
- outw(0x3ce, 0x25 + (pitch & 0xff00)); /* bits 8-11 */
- outw(0x3ce, 0x26 + (pitch << 8)); /* source pitch */
- outw(0x3ce, 0x27 + (pitch & 0xff00));
-
- outw(0x3ce, 0x28 + (destaddr << 8)); /* bits 0-7 of dest. address */
- outw(0x3ce, 0x29 + (destaddr & 0xff00)); /* bits 8-15 */
- outw(0x3ce, 0x2a + ((destaddr & 0x1f0000) >> 8)); /* bits 16-20 */
-
- outw(0x3ce, 0x2c + (srcaddr << 8)); /* bits 0-7 of src address */
- outw(0x3ce, 0x2d + (srcaddr & 0xff00)); /* bits 8-15 */
- outw(0x3ce, 0x2e + ((srcaddr & 0x1f0000) >> 8)); /* bits 16-20 */
-
- outw(0x3ce, 0x30 + blt_direction); /* normal blit */
- outw(0x3ce, 0x32 + 0x0d00); /* operation: copy */
- outw(0x3ce, 0x31 + 0x0200); /* start operation */
-
- return cirrus_bltwait();
- }
-
-
- static int cirrus_imageblt( unsigned *srcaddr, int destaddr, int w, int h,
- int pitch ) {
- int count;
- unsigned *base;
-
- w--;
- outw(0x3ce, 0x20 + (w << 8)); /* bits 0-7 of width */
- outw(0x3ce, 0x21 + (w & 0xff00)); /* bits 8-10 */
-
- h--;
- outw(0x3ce, 0x22 + (h << 8)); /* bits 0-7 of height */
- outw(0x3ce, 0x23 + (h & 0xff00)); /* bits 8-9 */
-
- outw(0x3ce, 0x24 + (pitch << 8)); /* bits 0-7 of dest. pitch */
- outw(0x3ce, 0x25 + (pitch & 0xff00)); /* bits 8-11 */
-
- /* source pitch not required */
-
- outw(0x3ce, 0x28 + (destaddr << 8)); /* bits 0-7 of dest. address */
- outw(0x3ce, 0x29 + (destaddr & 0xff00)); /* bits 8-15 */
- outw(0x3ce, 0x2a + ((destaddr & 0x1f0000) >> 8)); /* bits 16-20 */
-
- /* blit source address not required */
-
- outw(0x3ce, 0x30 + 0x0400); /* from system memory */
- outw(0x3ce, 0x32 + 0x0d00); /* operation: copy */
- outw(0x3ce, 0x31 + 0x0200); /* start operation */
-
- w++;
- h++;
- count = (w * h + 3) / 4; /* #longwords */
- /* This may not be quite right for the last few bytes */
-
- base = (unsigned *)(__svgalib_graph_mem + 4);
-
- #define USE_ASM
-
- {
- unsigned *srcp;
- unsigned *endp;
- srcp = srcaddr;
- endp = srcaddr + count;
- #ifdef USE_ASM
- while (srcp + 16 <= endp) {
- int t; /* temp. storage only */
- asm(
- "movl (%1),%0\n\t"
- "movl %0,(%2)\n\t"
- "movl 4(%1),%0\n\t"
- "movl %0,(%2)\n\t"
- "movl 8(%1),%0\n\t"
- "movl %0,(%2)\n\t"
- "movl 12(%1),%0\n\t"
- "movl %0,(%2)\n\t"
- "movl 16(%1),%0\n\t"
- "movl %0,(%2)\n\t"
- "movl 20(%1),%0\n\t"
- "movl %0,(%2)\n\t"
- "movl 24(%1),%0\n\t"
- "movl %0,(%2)\n\t"
- "movl 28(%1),%0\n\t"
- "movl %0,(%2)\n\t"
- "movl 32(%1),%0\n\t"
- "movl %0,(%2)\n\t"
- "movl 36(%1),%0\n\t"
- "movl %0,(%2)\n\t"
- "movl 40(%1),%0\n\t"
- "movl %0,(%2)\n\t"
- "movl 44(%1),%0\n\t"
- "movl %0,(%2)\n\t"
- "movl 48(%1),%0\n\t"
- "movl %0,(%2)\n\t"
- "movl 52(%1),%0\n\t"
- "movl %0,(%2)\n\t"
- "movl 56(%1),%0\n\t"
- "movl %0,(%2)\n\t"
- "movl 60(%1),%0\n\t"
- "movl %0,(%2)\n\t"
- : : "r" (t), "r" (srcp), "r" (base)
- );
- srcp += 16; /* add 16 * 4 to pointer */
- }
- #endif
- while (srcp < endp)
- *base = *(srcp++);
- }
-
- return cirrus_bltwait();
- }
-
-
- static int pattern = -1;
-
- static int initializepattern() {
- int i;
- int v;
- #if 0
- /* Write 8x8 monochrome pattern above claimed video memory. */
- v = VMEM;
- if (vga_claimvideomemory(VMEM + 8)) {
- printf("svgalib: Cannot allocate video memory for Cirrus fill pattern.\n");
- return 1;
- }
- pattern = v;
- #else
- pattern = cirrus_memory * 1024 - 256;
- #endif
- if (cirrus_inlinearmode())
- memset(vga_getgraphmem() + pattern, 0xff, 8);
- else {
- cirrus_driverspecs.setpage(pattern >> 16);
- memset(__svgalib_graph_mem + (pattern & 0xffff), 0xff, 8);
- }
- return 0;
- }
-
- static int cirrus_fillblt( int destaddr, int w, int h, int pitch, int c ) {
- int srcaddr;
-
- if (pattern == -1)
- if (initializepattern())
- return -1;
-
- srcaddr = pattern;
-
- outw(0x3ce, 0x2c + (srcaddr << 8)); /* bits 0-7 of src address */
- outw(0x3ce, 0x2d + (srcaddr & 0xff00)); /* bits 8-15 */
- outw(0x3ce, 0x2e + ((srcaddr & 0x1f0000) >> 8)); /* bits 16-20 */
-
- w--;
- outw(0x3ce, 0x20 + (w << 8)); /* bits 0-7 of width */
- outw(0x3ce, 0x21 + (w & 0xff00)); /* bits 8-10 */
-
- h--;
- outw(0x3ce, 0x22 + (h << 8)); /* bits 0-7 of height */
- outw(0x3ce, 0x23 + (h & 0xff00)); /* bits 8-9 */
-
- outw(0x3ce, 0x24 + (pitch << 8)); /* bits 0-7 of dest. pitch */
- outw(0x3ce, 0x25 + (pitch & 0xff00)); /* bits 8-11 */
-
- outw(0x3ce, 0x28 + (destaddr << 8)); /* bits 0-7 of dest. address */
- outw(0x3ce, 0x29 + (destaddr & 0xff00)); /* bits 8-15 */
- outw(0x3ce, 0x2a + ((destaddr & 0x1f0000) >> 8)); /* bits 16-20 */
-
- outw(0x3ce, 0x01 + (c << 8)); /* foreground color */
-
- outw(0x3ce, 0x30 + 0xc000); /* pattern fill, color expansion */
- outw(0x3ce, 0x32 + 0x0d00); /* operation: copy */
- outw(0x3ce, 0x31 + 0x0200); /* start operation */
-
- cirrus_bltwait();
-
- outw(0x3ce, 0x01); /* Disable Set/Reset. */
- }
-
- static int cirrus_hlinelistblt( int ymin, int n, int *xmin, int *xmax,
- int pitch, int c ) {
- int srcaddr, i;
-
- if (pattern == -1)
- if (initializepattern())
- return -1;
-
- srcaddr = pattern;
-
- /* registers that won't change */
-
- outw(0x3ce, 0x2c + (srcaddr << 8)); /* bits 0-7 of src address */
- outw(0x3ce, 0x2d + (srcaddr & 0xff00)); /* bits 8-15 */
- outw(0x3ce, 0x2e + ((srcaddr & 0x1f0000) >> 8)); /* bits 16-20 */
-
- outw(0x3ce, 0x24 + (pitch << 8)); /* bits 0-7 of dest. pitch */
- outw(0x3ce, 0x25 + (pitch & 0xff00)); /* bits 8-11 */
-
- outw(0x3ce, 0x30 + 0xc000); /* pattern fill, color expansion */
- outw(0x3ce, 0x01 + (c << 8)); /* foreground color */
- outw(0x3ce, 0x32 + 0x0d00); /* operation: copy */
- outb(0x3ce, 0x31);
-
- for (i = 0; i < n; i++) {
- int w;
- int destaddr;
- w = xmax[i] - xmin[i] - 1; /* discard rightmost pixel */
- if (w < 0) /* (and -1 for chip) */
- continue;
-
- while (inb(0x3cf) & 1); /* wait for blitter */
-
- outw(0x3ce, 0x20 + (w << 8)); /* bits 0-7 of width */
- outw(0x3ce, 0x21 + (w & 0x0700)); /* bits 8-10 */
-
- /* set height to 1 */
- outw(0x3ce, 0x22 + (0 << 8)); /* bits 0-7 of height */
- outw(0x3ce, 0x23 + (0 & 0x0300)); /* bits 8-9 */
-
- destaddr = (ymin + i) * pitch + xmin[i];
-
- outw(0x3ce, 0x28 + (destaddr << 8));
- outw(0x3ce, 0x29 + (destaddr & 0xff00));
- outw(0x3ce, 0x2a + ((destaddr & 0x1f0000) >> 8));
-
- outw(0x3ce, 0x31 + 0x0200); /* start operation */
-
- CRITICAL = 1;
- }
- cirrus_bltwait();
- CRITICAL = 0;
-
- outw(0x3ce, 0x01); /* Disable Set/Reset. */
- return 0;
- }
-
-
-
-
- /* Cirrus Logic acceleration functions implementation. */
-
- /* BitBLT modes. */
-
- #define FORWARDS 0x00
- #define BACKWARDS 0x01
- #define SYSTEMDEST 0x02
- #define SYSTEMSRC 0x04
- #define TRANSPARENCYCOMPARE 0x08
- #define PIXELWIDTH16 0x10
- #define PIXELWIDTH32 0x30 /* 543x only. */
- #define PATTERNCOPY 0x40
- #define COLOREXPAND 0x80
-
- /* Macros for normal I/O BitBLT register access. */
-
- #define SETSRCADDR(addr) \
- outw(0x3CE, (((addr) & 0x000000FF) << 8) | 0x2C); \
- outw(0x3CE, (((addr) & 0x0000FF00)) | 0x2D); \
- outw(0x3CE, (((addr) & 0x003F0000) >> 8) | 0x2E);
-
- #define SETDESTADDR(addr) \
- outw(0x3CE, (((addr) & 0x000000FF) << 8) | 0x28); \
- outw(0x3CE, (((addr) & 0x0000FF00)) | 0x29); \
- outw(0x3CE, (((addr) & 0x003F0000) >> 8) | 0x2A);
-
- /* Pitch: the 5426 goes up to 4095, the 5434 can do 8191. */
-
- #define SETDESTPITCH(pitch) \
- outw(0x3CE, (((pitch) & 0x000000FF) << 8) | 0x24); \
- outw(0x3CE, (((pitch) & 0x00001F00)) | 0x25);
-
- #define SETSRCPITCH(pitch) \
- outw(0x3CE, (((pitch) & 0x000000FF) << 8) | 0x26); \
- outw(0x3CE, (((pitch) & 0x00001F00)) | 0x27);
-
- /* Width: the 5426 goes up to 2048, the 5434 can do 8192. */
-
- #define SETWIDTH(width) \
- outw(0x3CE, ((((width) - 1) & 0x000000FF) << 8) | 0x20); \
- outw(0x3CE, ((((width) - 1) & 0x00001F00)) | 0x21);
-
- /* Height: the 5426 goes up to 1024, the 5434 can do 2048. */
- /* It appears many 5434's only go up to 1024. */
-
- #define SETHEIGHT(height) \
- outw(0x3CE, ((((height) - 1) & 0x000000FF) << 8) | 0x22); \
- outw(0x3CE, (((height) - 1) & 0x00000700) | 0x23);
-
- #define SETBLTMODE(m) \
- outw(0x3CE, ((m) << 8) | 0x30);
-
- #define SETBLTWRITEMASK(m) \
- outw(0x3CE, ((m) << 8) | 0x2F);
-
- #define SETTRANSPARENCYCOLOR(c) \
- outw(0x3CE, ((c) << 8) | 0x34);
-
- #define SETTRANSPARENCYCOLOR16(c) \
- outw(0x3CE, ((c) << 8) | 0x34); \
- outw(0x3CE, (c & 0xFF00) | 0x35);
-
- #define SETTRANSPARENCYCOLORMASK16(m) \
- outw(0x3CE, ((m) << 8) | 0x38); \
- outw(0x3CE, ((m) & 0xFF00) | 0x39);
-
- #define SETROP(rop) \
- outw(0x3CE, ((rop) << 8) | 0x32);
-
- #define SETFOREGROUNDCOLOR(c) \
- outw(0x3CE, 0x01 + ((c) << 8));
-
- #define SETBACKGROUNDCOLOR(c) \
- outw(0x3CE, 0x00 + ((c) << 8));
-
- #define SETFOREGROUNDCOLOR16(c) \
- outw(0x3CE, 0x01 + ((c) << 8)); \
- outw(0x3CE, 0x11 + ((c) & 0xFF00));
-
- #define SETBACKGROUNDCOLOR16(c) \
- outw(0x3CE, 0x00 + ((c) << 8)); \
- outw(0x3CE, 0x10 + ((c) & 0xFF00)); \
-
- #define SETFOREGROUNDCOLOR32(c) \
- outw(0x3CE, 0x01 + ((c) << 8)); \
- outw(0x3CE, 0x11 + ((c) & 0xFF00)); \
- outw(0x3CE, 0x13 + (((c) & 0xFf0000) >> 8)); \
- outw(0x3CE, 0x15 + (((unsigned int)(c) & 0xFF000000) >> 16));
-
- #define SETBACKGROUNDCOLOR32(c) \
- outw(0x3CE, 0x00 + ((c) << 8)); \
- outw(0x3CE, 0x10 + ((c) & 0xFF00)); \
- outw(0x3CE, 0x12 + (((c) & 0xFF0000) >> 8)); \
- outw(0x3CE, 0x14 + (((unsigned int)(c) & 0xFF000000) >> 16));
-
- #define STARTBLT() { \
- unsigned char tmp; \
- outb(0x3CE, 0x31); \
- tmp = inb(0x3CF); \
- outb(0x3CF, tmp | 0x02); \
- }
-
- #define BLTBUSY(s) { \
- outb(0x3CE, 0x31); \
- s = inb(0x3CF) & 1; \
- }
-
- #define WAITUNTILFINISHED() \
- for (;;) { \
- int busy; \
- BLTBUSY(busy); \
- if (!busy) \
- break; \
- }
-
-
- /* Macros for memory-mapped I/O BitBLT register access. */
-
- /* MMIO addresses (offset from 0xb8000). */
-
- #define MMIOBACKGROUNDCOLOR 0x00
- #define MMIOFOREGROUNDCOLOR 0x04
- #define MMIOWIDTH 0x08
- #define MMIOHEIGHT 0x0A
- #define MMIODESTPITCH 0x0C
- #define MMIOSRCPITCH 0x0E
- #define MMIODESTADDR 0x10
- #define MMIOSRCADDR 0x14
- #define MMIOBLTWRITEMASK 0x17
- #define MMIOBLTMODE 0x18
- #define MMIOROP 0x1A
- #define MMIOBLTSTATUS 0x40
-
- #define MMIOSETDESTADDR(addr) \
- *(unsigned int *)(mmio_base + MMIODESTADDR) = addr;
-
- #define MMIOSETSRCADDR(addr) \
- *(unsigned int *)(mmio_base + MMIOSRCADDR) = addr;
-
- /* Pitch: the 5426 goes up to 4095, the 5434 can do 8191. */
-
- #define MMIOSETDESTPITCH(pitch) \
- *(unsigned short *)(mmio_base + MMIODESTPITCH) = pitch;
-
- #define MMIOSETSRCPITCH(pitch) \
- *(unsigned short *)(mmio_base + MMIOSRCPITCH) = pitch;
-
- /* Width: the 5426 goes up to 2048, the 5434 can do 8192. */
-
- #define MMIOSETWIDTH(width) \
- *(unsigned short *)(mmio_base + MMIOWIDTH) = (width) - 1;
-
- /* Height: the 5426 goes up to 1024, the 5434 can do 2048. */
-
- #define MMIOSETHEIGHT(height) \
- *(unsigned short *)(mmio_base + MMIOHEIGHT) = (height) - 1;
-
- #define MMIOSETBLTMODE(m) \
- *(unsigned char *)(mmio_base + MMIOBLTMODE) = m;
-
- #define MMIOSETBLTWRITEMASK(m) \
- *(unsigned char *)(mmio_base + MMIOBLTWRITEMASK) = m;
-
- #define MMIOSETROP(rop) \
- *(unsigned char *)(mmio_base + MMIOROP) = rop;
-
- #define MMIOSTARTBLT() \
- *(unsigned char *)(mmio_base + MMIOBLTSTATUS) |= 0x02;
-
- #define MMIOBLTBUSY(s) \
- s = *(volatile unsigned char *)(mmio_base + MMIOBLTSTATUS) & 1;
-
- #define MMIOSETBACKGROUNDCOLOR(c) \
- *(unsigned char *)(mmio_base + MMIOBACKGROUNDCOLOR) = c;
-
- #define MMIOSETFOREGROUNDCOLOR(c) \
- *(unsigned char *)(mmio_base + MMIOFOREGROUNDCOLOR) = c;
-
- #define MMIOSETBACKGROUNDCOLOR16(c) \
- *(unsigned short *)(mmio_base + MMIOBACKGROUNDCOLOR) = c;
-
- #define MMIOSETFOREGROUNDCOLOR16(c) \
- *(unsigned short *)(mmio_base + MMIOFOREGROUNDCOLOR) = c;
-
- #define MMIOSETBACKGROUNDCOLOR32(c) \
- *(unsigned int *)(mmio_base + MMIOBACKGROUNDCOLOR) = c;
-
- #define MMIOSETFOREGROUNDCOLOR32(c) \
- *(unsigned int *)(mmio_base + MMIOFOREGROUNDCOLOR) = c;
-
- #define MMIOWAITUNTILFINISHED() \
- for (;;) { \
- int busy; \
- MMIOBLTBUSY(busy); \
- if (!busy) \
- break; \
- }
-
- static int cirrus_pattern_address; /* Pattern with 1's (8 bytes) */
- static int cirrus_bitblt_pixelwidth;
- /* Foreground color is not preserved on 5420/2/4/6/8. */
- static int cirrus_accel_foreground_color;
-
- void cirrusaccel_init( AccelSpecs *accelspecs, int bpp, int width_in_pixels ) {
- /* [Setup accelerator screen pitch] */
- /* [Prepare any required off-screen space] */
- if (bpp == 8)
- cirrus_bitblt_pixelwidth = 0;
- if (bpp == 16)
- cirrus_bitblt_pixelwidth = PIXELWIDTH16;
- if (bpp == 32)
- cirrus_bitblt_pixelwidth = PIXELWIDTH32;
- SETSRCPITCH(accel_screenpitchinbytes);
- SETDESTPITCH(accel_screenpitchinbytes);
- SETROP(0x0D);
- cirrus_pattern_address = cirrus_memory * 1024 - 8;
- (*driverspecs->setpage)(cirrus_pattern_address / 65536);
- *(unsigned *)(__svgalib_graph_mem + (cirrus_pattern_address & 0xFFFF))
- = 0xFFFFFFFF;
- *(unsigned *)(__svgalib_graph_mem + (cirrus_pattern_address & 0xFFFF)
- + 4) = 0xFFFFFFFF;
- (*driverspecs->setpage)(0);
- if (cirrus_chiptype >= CLGD5429)
- /* Enable memory-mapped I/O. */
- outSR(0x17, inSR(0x17) | 0x04);
- }
-
-
- /*
- * Note: The foreground color register must always be reset to 0
- * on the 542x to avoid problems in normal framebuffer operation.
- * This is not the case on chips that support memory-mapped I/O.
- */
-
- /*
- * These are two auxilliary functions to program the foreground
- * color depending on the current depth.
- */
-
- static void set_foreground_color( int fg ) {
- if (accel_bytesperpixel == 1) {
- SETFOREGROUNDCOLOR(fg);
- return;
- }
- if (accel_bytesperpixel == 2) {
- SETFOREGROUNDCOLOR16(fg);
- return;
- }
- SETFOREGROUNDCOLOR32(fg);
- }
-
- static void mmio_set_foreground_color( int fg ) {
- if (accel_bytesperpixel == 1) {
- MMIOSETFOREGROUNDCOLOR(fg);
- return;
- }
- if (accel_bytesperpixel == 2) {
- MMIOSETFOREGROUNDCOLOR16(fg);
- return;
- }
- MMIOSETFOREGROUNDCOLOR32(fg);
- }
-
- #define FINISHBACKGROUNDBLITS() \
- if (accel_mode & BLITS_IN_BACKGROUND) \
- WAITUNTILFINISHED();
-
- #define MMIOFINISHBACKGROUNDBLITS() \
- if (accel_mode & BLITS_IN_BACKGROUND) \
- MMIOWAITUNTILFINISHED();
-
- void cirrusaccel_FillBox( int x, int y, int width, int height ) {
- int destaddr;
- destaddr = BLTBYTEADDRESS(x, y);
- width *= accel_bytesperpixel;
- FINISHBACKGROUNDBLITS();
- SETSRCADDR(cirrus_pattern_address);
- SETDESTADDR(destaddr);
- SETWIDTH(width);
- SETHEIGHT(height);
- set_foreground_color(cirrus_accel_foreground_color);
- SETBLTMODE(COLOREXPAND | PATTERNCOPY | cirrus_bitblt_pixelwidth);
- STARTBLT();
- WAITUNTILFINISHED();
- /* Can't easily run in background because foreground color has */
- /* to be restored. */
- SETFOREGROUNDCOLOR(0x00);
- }
-
- void cirrusaccel_mmio_FillBox( int x, int y, int width, int height ) {
- int destaddr;
- destaddr = BLTBYTEADDRESS(x, y);
- width *= accel_bytesperpixel;
- MMIOFINISHBACKGROUNDBLITS();
- MMIOSETSRCADDR(cirrus_pattern_address);
- MMIOSETDESTADDR(destaddr);
- MMIOSETWIDTH(width);
- MMIOSETHEIGHT(height);
- MMIOSETBLTMODE(COLOREXPAND | PATTERNCOPY | cirrus_bitblt_pixelwidth);
- MMIOSTARTBLT();
- if (!(accel_mode & BLITS_IN_BACKGROUND))
- MMIOWAITUNTILFINISHED();
- }
-
- void cirrusaccel_ScreenCopy( int x1, int y1, int x2, int y2, int width,
- int height) {
- int srcaddr, destaddr, dir;
- width *= accel_bytesperpixel;
- srcaddr = BLTBYTEADDRESS(x1, y1);
- destaddr = BLTBYTEADDRESS(x2, y2);
- dir = FORWARDS;
- if ((y1 < y2 || (y1 == y2 && x1 < x2))
- && y1 + height > y2) {
- srcaddr += (height - 1) * accel_screenpitchinbytes + width - 1;
- destaddr += (height - 1) * accel_screenpitchinbytes + width - 1;
- dir = BACKWARDS;
- }
- FINISHBACKGROUNDBLITS();
- SETSRCADDR(srcaddr);
- SETDESTADDR(destaddr);
- SETWIDTH(width);
- SETHEIGHT(height);
- SETBLTMODE(dir);
- STARTBLT();
- if (!(accel_mode & BLITS_IN_BACKGROUND))
- WAITUNTILFINISHED();
- }
-
- void cirrusaccel_mmio_ScreenCopy( int x1, int y1, int x2, int y2, int width,
- int height) {
- int srcaddr, destaddr, dir;
- width *= accel_bytesperpixel;
- srcaddr = BLTBYTEADDRESS(x1, y1);
- destaddr = BLTBYTEADDRESS(x2, y2);
- dir = FORWARDS;
- if ((y1 < y2 || (y1 == y2 && x1 < x2))
- && y1 + height > y2) {
- srcaddr += (height - 1) * accel_screenpitchinbytes + width - 1;
- destaddr += (height - 1) * accel_screenpitchinbytes + width - 1;
- dir = BACKWARDS;
- }
- MMIOFINISHBACKGROUNDBLITS();
- MMIOSETSRCADDR(srcaddr);
- MMIOSETDESTADDR(destaddr);
- MMIOSETWIDTH(width);
- MMIOSETHEIGHT(height);
- MMIOSETBLTMODE(dir);
- MMIOSTARTBLT();
- if (!(accel_mode & BLITS_IN_BACKGROUND))
- MMIOWAITUNTILFINISHED();
- }
-
- void cirrusaccel_SetFGColor( int fg ) {
- cirrus_accel_foreground_color = fg;
- }
-
- void cirrusaccel_mmio_SetFGColor( int fg ) {
- MMIOFINISHBACKGROUNDBLITS();
- mmio_set_foreground_color(fg);
- }
-
- static unsigned char cirrus_rop_map[] = {
- 0x0D, /* ROP_COPY */
- 0x6D, /* ROP_OR */
- 0x05, /* ROP_AND */
- 0x59, /* ROP_XOR */
- 0x0B /* ROP_INVERT */
- };
-
- void cirrusaccel_SetRasterOp( int rop ) {
- FINISHBACKGROUNDBLITS();
- SETROP(cirrus_rop_map[rop]);
- }
-
- void cirrusaccel_mmio_SetRasterOp( int rop ) {
- MMIOFINISHBACKGROUNDBLITS();
- MMIOSETROP(cirrus_rop_map[rop]);
- }
-
- void cirrusaccel_SetTransparency( int mode, int color ) {
- FINISHBACKGROUNDBLITS();
- if (mode == DISABLE_TRANSPARENCY_COLOR) {
- /* Disable. */
- SETTRANSPARENCYCOLORMASK16(0xFFFF);
- return;
- }
- if (mode == ENABLE_TRANSPARENCY_COLOR) {
- if (accel_bytesperpixel == 1)
- color += color << 8;
- SETTRANSPARENCYCOLORMASK16(0x0000);
- SETTRANSPARENCYCOLOR16(color);
- return;
- }
- if (mode == DISABLE_BITMAP_TRANSPARENCY) {
- accel_bitmaptransparency = 0;
- return;
- }
- /* mode == ENABLE_BITMAP_TRANSPARENCY */
- accel_bitmaptransparency = 1;
- }
-
- void cirrusaccel_Sync() {
- WAITUNTILFINISHED();
- }
-
- void cirrusaccel_mmio_Sync() {
- MMIOWAITUNTILFINISHED();
- }
-
-
- /*
- * Set up accelerator interface for pixels of size bpp and scanline width
- * of width_in_pixels.
- */
-
- void init_acceleration_specs_for_mode( AccelSpecs *accelspecs, int bpp,
- int width_in_pixels ) {
- accelspecs->operations = 0;
- accelspecs->ropOperations = 0;
- accelspecs->transparencyOperations = 0;
- if (cirrus_chiptype >= CLGD5426) {
- accelspecs->operations |= ACCELFLAG_SETMODE | ACCELFLAG_SYNC;
- if (bpp == 8 || bpp == 16) {
- /* BitBLT engine available. */
- accelspecs->operations |=
- ACCELFLAG_FILLBOX | ACCELFLAG_SETFGCOLOR |
- ACCELFLAG_SCREENCOPY |
- ACCELFLAG_SETRASTEROP |
- ACCELFLAG_SETTRANSPARENCY;
- accelspecs->ropOperations =
- ACCELFLAG_FILLBOX | ACCELFLAG_SCREENCOPY;
- accelspecs->transparencyOperations =
- ACCELFLAG_SCREENCOPY;
- }
- if (bpp == 24) {
- /* Depth-independent BitBLT functions. */
- accelspecs->operations |=
- ACCELFLAG_SCREENCOPY;
- accelspecs->ropOperations =
- ACCELFLAG_SCREENCOPY;
- }
- }
- if (cirrus_chiptype >= CLGD5429)
- if (bpp == 8 || bpp == 16) {
- /* Newer chips don't have true color-compare. */
- accelspecs->operations &= ~ACCELFLAG_SETTRANSPARENCY;
- accelspecs->transparencyOperations = 0;
- }
- if (cirrus_chiptype >= CLGD5434)
- if (bpp == 32) {
- /* BitBLT engine available for 32bpp. */
- accelspecs->operations |=
- ACCELFLAG_FILLBOX | ACCELFLAG_SETFGCOLOR |
- ACCELFLAG_SCREENCOPY |
- ACCELFLAG_SETRASTEROP |
- ACCELFLAG_SETTRANSPARENCY;
- accelspecs->ropOperations =
- ACCELFLAG_FILLBOX | ACCELFLAG_SCREENCOPY;
- }
- #if 0 /* Full potential. */
- /* 5420 */
- if (bpp == 8)
- /* Color-expand (extended write modes). */
- accelspecs->operations =
- ACCELFLAG_FILLBOX | ACCELFLAG_SETFGCOLOR | ACCELFLAG_DRAWHLINE |
- ACCELFLAG_DRAWHLINELIST;
- if (cirrus_chiptype >= CLGD5422)
- if (bpp == 16)
- /* Also for 16bpp. */
- accelspecs->operations =
- ACCELFLAG_FILLBOX | ACCELFLAG_SETFGCOLOR |
- ACCELFLAG_DRAWHLINE | ACCELFLAG_DRAWHLINELIST;
- if (cirrus_chiptype >= CLGD5426 && cirrus_memory >= 1024) {
- if (bpp == 8 || bpp == 16) {
- /* BitBLT engine available. */
- accelspecs->operations |=
- ACCELFLAG_SCREENCOPY | ACCELFLAG_PUTIMAGE |
- ACCELFLAG_SETBGCOLOR | ACCELFLAG_SETRASTEROP |
- ACCELFLAG_SETTRANSPARENCY |
- ACCELFLAG_PUTIMAGE | ACCELFLAG_PUTBITMAP
- ACCELFLAG_SCREENCOPYBITMAP;
- accelspecs->ropOperations =
- ACCELFLAG_FILLBOX | ACCELFLAG_SCREENCOPY |
- ACCELFLAG_PUTIMAGE;
- accelspecs->transparencyOperations =
- ACCELFLAG_SCREENCOPY | ACCELFLAG_PUTIMAGE |
- ACCELFLAG_PUTBITMAP;
- }
- if (bpp == 24) {
- /* Depth-independent BitBLT functions. */
- accelspecs->operations |=
- ACCELFLAG_SCREENCOPY | ACCELFLAG_PUTIMAGE;
- accelspecs->ropOperations =
- ACCELFLAG_SCREENCOPY | ACCELFLAG_PUTIMAGE;
- /*
- * Possible additions: FILLBOX in bands, and
- * weird PutBitmap with color 0x000000 (trippling
- * bits with 8bpp operation).
- */
- }
- }
- if (cirrus_chiptype >= CLGD5429)
- if (bpp == 8 || bpp == 16) {
- /* Newer chips don't have true color-compare. */
- accelspecs->transparencyOperations = ACCELFLAG_BITMAP;
- }
- if (cirrus_chiptype >= CLGD5434)
- if (bpp == 32) {
- /* BitBLT engine available for 32bpp. */
- accelspecs->operations |=
- ACCELFLAG_SCREENCOPY | ACCELFLAG_PUTIMAGE |
- ACCELFLAG_SETBGCOLOR | ACCELFLAG_SETRASTEROP |
- ACCELFLAG_SETTRANSPARENCY |
- ACCELFLAG_PUTIMAGE | ACCELFLAG_PUTBITMAP
- ACCELFLAG_SCREENCOPYBITMAP |
- ACCELFLAG_DRAWHLINE | ACCELFLAG_DRAWHLINELIST;
- accelspecs->ropOperations =
- ACCELFLAG_FILLBOX |
- ACCELFLAG_SCREENCOPY | ACCELFLAG_PUTIMAGE;
- accelspecs->transparencyOperations =
- ACCELFLAG_PUTBITMAP;
- }
- #endif
- /* Set the function pointers; availability is handled by flags. */
- accelspecs->FillBox = cirrusaccel_FillBox;
- accelspecs->ScreenCopy = cirrusaccel_ScreenCopy;
- accelspecs->SetFGColor = cirrusaccel_SetFGColor;
- accelspecs->SetTransparency = cirrusaccel_SetTransparency;
- accelspecs->SetRasterOp = cirrusaccel_SetRasterOp;
- accelspecs->Sync = cirrusaccel_Sync;
- if (cirrus_chiptype >= CLGD5429) {
- accelspecs->FillBox = cirrusaccel_mmio_FillBox;
- accelspecs->ScreenCopy = cirrusaccel_mmio_ScreenCopy;
- accelspecs->SetFGColor = cirrusaccel_mmio_SetFGColor;
- /* No mmio-version of SetTransparency. */
- accelspecs->SetRasterOp = cirrusaccel_mmio_SetRasterOp;
- accelspecs->Sync = cirrusaccel_mmio_Sync;
- }
- }
-