home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / D / SVGALIB / SVGALIB1.TAR / svgalib / src / cirrus.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-02-22  |  55.6 KB  |  1,994 lines

  1. /* VGAlib version 1.2 - (c) 1993 Tommy Frandsen            */
  2. /*                                   */
  3. /* This library is free software; you can redistribute it and/or   */
  4. /* modify it without any restrictions. This library is distributed */
  5. /* in the hope that it will be useful, but without any warranty.   */
  6.  
  7. /* Cirrus support Copyright (C) 1993 Harm Hanemaayer */
  8.  
  9. /*
  10.  * Dec 1994:
  11.  * 
  12.  * Mode setting rewritten with more SVGA generalization and increased
  13.  * flexibility. Supports 542x/543x.
  14.  * Uses interfaces in timing.h and vgaregs.h. Only saves/restores
  15.  * extended registers that are actually changed for SVGA modes.
  16.  */
  17.  
  18.  
  19. #include <stdlib.h>
  20. #include <stdio.h>    /* for printf */
  21. #include <string.h>    /* for memset */
  22. #include <sys/mman.h>    /* mmap */
  23. #include "vga.h"
  24. #include "libvga.h"
  25. #include "driver.h"
  26.  
  27.  
  28. /* Enable support for > 85 MHz dot clocks on the 5434. */
  29. #define SUPPORT_5434_PALETTE_CLOCK_DOUBLING
  30. /* Use the special clocking mode for all dot clocks at 256 colors, not */
  31. /* just those > 85 MHz, for debugging. */
  32. /* #define ALWAYS_USE_5434_PALETTE_CLOCK_DOUBLING */
  33.  
  34.  
  35. /* New style driver interface. */
  36. #include "timing.h"
  37. #include "vgaregs.h"
  38. #include "interface.h"
  39. #include "accel.h"
  40.  
  41. #define CIRRUSREG_GR(i) (VGA_TOTAL_REGS + i - VGA_GRAPHICS_COUNT)
  42. #define CIRRUSREG_SR(i) (VGA_TOTAL_REGS + 5 + i - VGA_SEQUENCER_COUNT)
  43. #define CIRRUSREG_CR(i) (VGA_TOTAL_REGS + 5 + 27 + i - VGA_CRTC_COUNT)
  44. #define CIRRUSREG_DAC (VGA_TOTAL_REGS + 5 + 27 + 15)
  45. #define CIRRUS_TOTAL_REGS (VGA_TOTAL_REGS + 5 + 27 + 15 + 1)
  46.  
  47. /* Indices into mode register array. */
  48. #define CIRRUS_GRAPHICSOFFSET1    CIRRUSREG_GR(0x09)
  49. #define CIRRUS_GRAPHICSOFFSET2    CIRRUSREG_GR(0x0A)
  50. #define CIRRUS_GRB        CIRRUSREG_GR(0x0B)
  51. #define CIRRUS_SR7        CIRRUSREG_SR(0x07)
  52. #define CIRRUS_VCLK3NUMERATOR    CIRRUSREG_SR(0x0E)
  53. #define CIRRUS_DRAMCONTROL    CIRRUSREG_SR(0x0F)
  54. #define CIRRUS_PERFTUNING    CIRRUSREG_SR(0x16)
  55. #define CIRRUS_SR17        CIRRUSREG_SR(0x17)
  56. #define CIRRUS_VCLK3DENOMINATOR CIRRUSREG_SR(0x1E)
  57. #define CIRRUS_MCLKREGISTER    CIRRUSREG_SR(0x1F)
  58. #define CIRRUS_CR19        CIRRUSREG_CR(0x19)
  59. #define CIRRUS_CR1A        CIRRUSREG_CR(0x1A)
  60. #define CIRRUS_CR1B        CIRRUSREG_CR(0x1B)
  61. #define CIRRUS_CR1D         CIRRUSREG_CR(0x1D)
  62. #define CIRRUS_HIDDENDAC    CIRRUSREG_DAC
  63.  
  64.  
  65. /* Efficient chip type checks. */
  66.  
  67. #define CHECKCHIP1(c1) ((1 << cirrus_chiptype) & (1 << c1))
  68. #define CHECKCHIP2(c1, c2) ((1 << cirrus_chiptype) & ((1 << c1) | (1 << c2)))
  69. #define CHECKCHIP3(c1, c2, c3) ((1 << cirrus_chiptype) & ((1 << c1) \
  70.     | (1 << c2) | (1 << c3)))
  71. #define CHECKCHIP4(c1, c2, c3, c4) ((1 << cirrus_chiptype) & ((1 << c1) \
  72.     | (1 << c2) | (1 << c3) | (1 << c4)))
  73. #define CHECKCHIP6(c1, c2, c3, c4, c5, c6) ((1 << cirrus_chiptype) & \
  74.     ((1 << c1) | (1 << c2) | (1 << c3) | (1 << c4) | (1 << c5) \
  75.     | (1 << c6)))
  76. #define CHECKCHIP8(c1, c2, c3, c4, c5, c6, c7, c8) ((1 << cirrus_chiptype) & \
  77.     ((1 << c1) | (1 << c2) | (1 << c3) | (1 << c4) | (1 << c5) \
  78.     | (1 << c6) | (1 << c7) | (1 << c8)))
  79. #define CHECKCHIPGREATEREQUAL(c) (cirrus_chiptype >= c)
  80. #define CHECKCHIPNOTEQUAL(c) (cirrus_chiptype != c)
  81.  
  82. #define CHIP_HAS_CR1D() \
  83.     CHECKCHIP3(CLGD5429, CLGD5430, CLGD5434)
  84. #define CHIP_HAS_GRC_AND_GRD() \
  85.     CHECKCHIP4(CLGD5424, CLGD5426, CLGD5428, CLGD5429)
  86. #define CHIP_HAS_GRE() \
  87.     CHECKCHIP4(CLGD5428, CLGD5429, CLGD5430, CLGD5434)
  88. #define CHIP_HAS_GR10_AND_GR11() \
  89.     CHECKCHIP6(CLGD5424, CLGD5426, CLGD5428, CLGD5429, CLGD5430, CLGD5434)
  90. #define CHIP_HAS_BLTTRANSPARENTCOLOR() \
  91.     CHECKCHIP2(CLGD5426, CLGD5428)
  92. #define CHIP_HAS_PERFTUNINGREGISTER() \
  93.     CHECKCHIP6(CLGD5424, CLGD5426, CLGD5428, CLGD5429, CLGD5430, CLGD5434)
  94. #define CHIP_HAS_MCLK_REGISTER() \
  95.     CHECKCHIP8(CLGD5420B, CLGD5422C, CLGD5424, CLGD5426, CLGD5428, \
  96.         CLGD5429, CLGD5430, CLGD5434)
  97. #define CHIP_HAS_32BIT_DRAM_BUS() \
  98.     CHECKCHIPGREATEREQUAL(CLGD5420B)
  99. #define CHIP_HAS_64BIT_DRAM_BUS() \
  100.     CHECKCHIP1(CLGD5434)
  101. #define CHIP_HAS_HIDDENDAC() \
  102.     CHECKCHIPGREATEREQUAL(CLGD5420B)
  103. #define CHIP_HAS_ACCELERATION() \
  104.     CHECKCHIPNOTEQUAL(CLGD5420B)
  105. #define CHIP_HAS_SR17() \
  106.     CHECKCHIPGREATEREQUAL(CLGD5422)
  107.  
  108.  
  109. /* CLOCK_FACTOR is double the osc freq in kHz (osc = 14.31818 MHz) */
  110. #define CLOCK_FACTOR 28636
  111.  
  112. /* clock in kHz is (numer * CLOCK_FACTOR / (denom & 0x3E)) >> (denom & 1) */
  113. #define CLOCKVAL(n, d) \
  114.      ((((n) & 0x7F) * CLOCK_FACTOR / ((d) & 0x3E)) >> ((d) & 1))
  115.  
  116.  
  117. static int cirrus_init(int, int, int);
  118. static void cirrus_unlock();
  119.  
  120. static int cirrus_memory;
  121. static int cirrus_chiptype;
  122. static int cirrus_chiprev;
  123. static unsigned char actualMCLK, programmedMCLK;
  124. static int DRAMbandwidth, DRAMbandwidthLimit;
  125. static unsigned char *mmio_base;
  126.  
  127.  
  128. static CardSpecs *cardspecs;
  129.  
  130. #define NU_FIXED_CLOCKS 19
  131.  
  132. /* 12.588 clock (0x33, 0x3B) replaced with 12.599 (0x2C, 0x33). */
  133.  
  134. static int cirrus_fixed_clocks[NU_FIXED_CLOCKS] = {
  135.     12599, 25227, 28325, 31500, 36025, 37747, 39992, 41164,
  136.     45076, 49867, 64983, 72163, 75000, 80013, 85226, 89998,
  137.     95019, 100226, 108035
  138. };
  139.  
  140. static unsigned char fixed_clock_numerator[NU_FIXED_CLOCKS] = {
  141.     0x2C, 0x4A, 0x5B, 0x42, 0x4E, 0x3A, 0x51, 0x45,
  142.     0x55, 0x65, 0x76, 0x7E, 0x6E, 0x5F, 0x7D, 0x58,
  143.     0x49, 0x46, 0x53
  144. };
  145.  
  146. static unsigned char fixed_clock_denominator[NU_FIXED_CLOCKS] = {
  147.     0x33, 0x2B, 0x2F, 0x1F, 0x3E, 0x17, 0x3A, 0x30,
  148.     0x36, 0x3A, 0x34, 0x32, 0x2A, 0x22, 0x2A, 0x1C,
  149.     0x16, 0x14, 0x16
  150. };
  151.  
  152. /*
  153.  * It looks like the 5434 palette clock doubling mode doensn't like
  154.  * clocks like (0x7B, 0x20), whereas (0x53, 0x16) is OK.
  155.  */
  156.  
  157. enum { CLGD5420 = 0, CLGD5420B, CLGD5422, CLGD5422C, CLGD5424, CLGD5426,
  158.     CLGD5428, CLGD5429, CLGD5430, CLGD5434};
  159.  
  160.  
  161. int cirrus_inlinearmode() {
  162.     outb(0x3c4, 0x07);
  163.     return (inb(0x3c5) & 0xf0) != 0;
  164. }
  165.  
  166. /* Fill in chipset specific mode information */
  167.  
  168. static void cirrus_getmodeinfo( int mode, vga_modeinfo *modeinfo ) {
  169.     if (modeinfo->bytesperpixel > 0)
  170.         modeinfo->maxpixels = cirrus_memory * 1024 / modeinfo->bytesperpixel;
  171.     else
  172.         /* 16-color SVGA mode */
  173.         /* Value taken from the air. */
  174.         modeinfo->maxpixels = cirrus_memory * 2048;
  175.     modeinfo->maxlogicalwidth = 4088;
  176. #if 0
  177.     if (mode != G320x200x256) {
  178.     /* No need to check for 320x200x256, we now have a special */
  179.     /* SVGA-derived 320x200x256 mode that fully supports page */
  180.     /* flipping etc. */
  181. #endif    
  182.         modeinfo->startaddressrange = cirrus_memory * 1024 - 1;
  183.         if (modeinfo->bytesperpixel == 1 &&
  184.             cirrus_chiptype >= CLGD5426 &&
  185.             (VMEM == -1 ? modeinfo->linewidth * modeinfo->height :
  186.             VMEM) <= (cirrus_memory * 1024 - 64)
  187.             && modeinfo->bytesperpixel == 1) {
  188. #if 0    /* Fix in the next release (disabled in 1.21) */
  189.             modeinfo->haveblit = HAVE_FILLBLIT | HAVE_BITBLIT |
  190.                 HAVE_IMAGEBLIT;
  191. #else
  192.             modeinfo->haveblit = HAVE_FILLBLIT;
  193. #endif            
  194.             /* 64 bytes are used a fill pattern */
  195.             modeinfo->maxpixels = (cirrus_memory * 1024 - 64)
  196.                 / modeinfo->bytesperpixel;
  197.         }
  198.         else
  199.             modeinfo->haveblit = 0;
  200. #if 0
  201.     }
  202.     else {
  203.         modeinfo->startaddressrange = 0xffff;
  204.         modeinfo->maxpixels = 65536;
  205.         modeinfo->haveblit = 0;
  206.     }
  207. #endif
  208. #if 0    /* Who cares. */
  209.     if (cirrus_interlaced(mode))
  210.       modeinfo->flags |= IS_INTERLACED;
  211. #endif
  212.     modeinfo->flags &= ~HAVE_RWPAGE;
  213.  
  214.     if (modeinfo->bytesperpixel >= 1) {
  215.         modeinfo->flags |= CAPABLE_LINEAR;
  216.         if (cirrus_inlinearmode())
  217.             modeinfo->flags |= IS_LINEAR;
  218.     }
  219. }
  220.  
  221.  
  222. /* Read and save chipset-specific registers */
  223.  
  224. static int cirrus_saveregs( unsigned char regs[] ) {
  225.         int i;
  226.  
  227. /*    #ifdef DEBUG
  228.     printf("Saving Cirrus extended registers.\n");
  229.     #endif
  230. */    
  231.     cirrus_unlock(); /* May be locked again by other programs (e.g. X) */
  232.  
  233. #if 0
  234.     /* Save extended CRTC registers. */
  235.     for (i = 0; i < 15; i++) {    /* was 4 */
  236.         port_out(0x18 + i, CRT_I);
  237.         regs[CIRRUSREG_CR(i)] = port_in(CRT_D);
  238.     }
  239.     
  240.     /* Save extended graphics registers */
  241.     for (i = 0; i < 5; i++) {    /* was 3 */
  242.         port_out(0x09 + i, GRA_I);
  243.         regs[CIRRUSREG_GR(i)] = port_in(GRA_D);
  244.     }
  245.  
  246.         /* Save extended sequencer registers. */
  247.         for (i = 0; i < 27; i++) {
  248.          port_out(0x05 + i, SEQ_I); 
  249.          regs[CIRRUSREG_SR(i)] = port_in(SEQ_D); 
  250.         }
  251. #endif
  252.  
  253.      /* Save extended CRTC registers. */
  254.      regs[CIRRUSREG_CR(0x19)] = inCR(0x19);
  255.      regs[CIRRUSREG_CR(0x1A)] = inCR(0x1A);
  256.      regs[CIRRUSREG_CR(0x1B)] = inCR(0x1B);
  257.     if (CHIP_HAS_CR1D())
  258.          regs[CIRRUSREG_CR(0x1D)] = inCR(0x1D);
  259.  
  260.     /* Save extended graphics registers. */
  261.     regs[CIRRUSREG_GR(0x09)] = inGR(0x09);
  262.     regs[CIRRUSREG_GR(0x0A)] = inGR(0x0A);
  263.     regs[CIRRUSREG_GR(0x0B)] = inGR(0x0B);
  264.  
  265.         /* Save extended sequencer registers. */
  266.         regs[CIRRUS_SR7] = inSR(0x07);
  267.         regs[CIRRUS_VCLK3NUMERATOR] = inSR(0x0E);
  268.         regs[CIRRUS_DRAMCONTROL] = inSR(0x0F);
  269.         if (CHIP_HAS_PERFTUNINGREGISTER())
  270.             regs[CIRRUS_PERFTUNING] = inSR(0x16);
  271.     if (CHIP_HAS_SR17())
  272.         regs[CIRRUS_SR17] = inSR(0x17);
  273.         regs[CIRRUS_VCLK3DENOMINATOR] = inSR(0x1E);
  274.         if (CHIP_HAS_MCLK_REGISTER())
  275.             regs[CIRRUS_MCLKREGISTER] = inSR(0x1F);
  276.  
  277.         /* Save Hicolor DAC register. */
  278.         if (CHIP_HAS_HIDDENDAC()) {
  279.             outb(0x3c6, 0);    outb(0x3c6, 0xff);
  280.             inb(0x3c6); inb(0x3c6); inb(0x3c6); inb(0x3c6);
  281.             regs[CIRRUSREG_DAC] = inb(0x3c6);
  282.     }
  283.  
  284.     return CIRRUS_TOTAL_REGS - VGA_TOTAL_REGS;
  285. }
  286.  
  287. static void writehicolordac( unsigned char c ) {
  288.         outb(0x3c6, 0);    outb(0x3c6, 0xff);
  289.         inb(0x3c6); inb(0x3c6); inb(0x3c6); inb(0x3c6);
  290.         outb(0x3c6, c);
  291.         inb(0x3c8);
  292. }
  293.  
  294.  
  295. /* Set chipset-specific registers */
  296.  
  297. static void cirrus_setregs( const unsigned char regs[], int mode )
  298. {
  299.         int i;
  300.         
  301. /*    #ifdef DEBUG
  302.     printf("Setting Cirrus extended registers.\n");
  303.      #endif
  304. */ 
  305.     cirrus_unlock(); /* May be locked again by other programs (eg. X) */
  306.  
  307.      /* Write extended CRTC registers. */
  308.      outCR(0x19, regs[CIRRUSREG_CR(0x19)]);
  309.      outCR(0x1A, regs[CIRRUSREG_CR(0x1A)]);
  310.      outCR(0x1B, regs[CIRRUSREG_CR(0x1B)]);
  311.     if (CHIP_HAS_CR1D())
  312.          outCR(0x1D, regs[CIRRUSREG_CR(0x1D)]);
  313.  
  314.     /* Write extended graphics registers. */
  315.     outGR(0x09, regs[CIRRUSREG_GR(0x09)]);
  316.     outGR(0x0A, regs[CIRRUSREG_GR(0x0A)]);
  317.     outGR(0x0B, regs[CIRRUSREG_GR(0x0B)]);
  318. #ifdef SET_ALL
  319.      if (CHIP_HAS_GRC_AND_GRD()) {
  320.          outGR(0x0C, regs[CIRRUSREG_GR(0x0C)]);
  321.          outGR(0x0D, regs[CIRRUSREG_GR(0x0D)]);
  322.      }
  323.      if (CHIP_HAS_GRE())
  324.          outGR(0x0E, regs[CIRRUSREG_GR(0x0E)];
  325.      if (CHIP_HAS_GR10_AND_GR11() {
  326.          outGR(0x10, regs[CIRRUSREG_GR(0x10)]);
  327.          outGR(0x11, regs[CIRRUSREG_GR(0x11)]);
  328.      }
  329.      if (CHIP_HAS_BLT_REGISTERS()) {
  330.         for (i = 0x20; i <= 0x2A; i++)
  331.              outGR(i, regs[CIRRUSREG_GR(i)]);
  332.         for (i = 0x2C; i < 0x2E; i++)
  333.              outGR(i, regs[CIRRUSREG_GR(i)]);
  334.          if (CHIP_HAS_BLTWRITEMASK())
  335.              outGR(0x2D, regs[CIRRUSREG_GR(0x2D));
  336.          outGR(0x30, regs[CIRRUSREG_GR(0x30));
  337.          outGR(0x32, regs[CIRRUSREG_GR(0x32));
  338.          if (CHIP_HAS_BLTTRANSPARENTCOLOR()) {
  339.              outGR(0x34, regs[CIRRUSREG_GR(0x34));
  340.              outGR(0x35, regs[CIRRUSREG_GR(0x35));
  341.              outGR(0x38, regs[CIRRUSREG_GR(0x38));
  342.              outGR(0x39, regs[CIRRUSREG_GR(0x39));
  343.          }
  344.      }
  345.  #endif
  346.  
  347.          /* Write Truecolor DAC register. */
  348.     if (CHIP_HAS_HIDDENDAC())
  349.             writehicolordac(regs[CIRRUS_HIDDENDAC]);
  350.  
  351.         /* Write extended sequencer registers. */
  352.  
  353.         /* Be careful to put the sequencer clocking mode in a safe state. */
  354.         outSR(0x07, (regs[CIRRUS_SR7] & ~0x0F) | 0x01);
  355.  
  356.         outSR(0x0E, regs[CIRRUS_VCLK3NUMERATOR]);
  357.         outSR(0x1E, regs[CIRRUS_VCLK3DENOMINATOR]);
  358.         outSR(0x07, regs[CIRRUS_SR7]);
  359.         outSR(0x0F, regs[CIRRUS_DRAMCONTROL]);
  360.         if (CHIP_HAS_PERFTUNINGREGISTER())
  361.             outSR(0x16, regs[CIRRUS_PERFTUNING]);
  362.     if (CHIP_HAS_SR17())
  363.         outSR(0x17, regs[CIRRUS_SR17]);
  364.         if (CHIP_HAS_MCLK_REGISTER())
  365.             outSR(0x1F, regs[CIRRUS_MCLKREGISTER]);
  366. }
  367.  
  368.  
  369. /* Return nonzero if mode is available */
  370.  
  371. static int cirrus_modeavailable( int mode ) {
  372.     struct info *info;
  373.     ModeTiming *modetiming;
  374.     ModeInfo *modeinfo;
  375.  
  376.     if ((mode < G640x480x256 && mode != G320x200x256)
  377.     || mode == G720x348x2)
  378.         return vga_driverspecs.modeavailable(mode);
  379.  
  380.     info = &__svgalib_infotable[mode];
  381.     if (cirrus_memory * 1024 < info->ydim * info->xbytes)
  382.         return 0;
  383.  
  384.     modeinfo = createModeInfoStructureForSvgalibMode(mode);
  385.  
  386.     modetiming = malloc(sizeof(ModeTiming));
  387.     if (getmodetiming(modetiming, modeinfo, cardspecs)) {
  388.         free(modetiming);
  389.         free(modeinfo);
  390.         return 0;
  391.     }
  392.     free(modetiming);
  393.     free(modeinfo);
  394.  
  395.     return SVGADRV;
  396. }
  397.  
  398.  
  399. /* Set a mode */
  400.  
  401. /* Local, called by cirrus_setmode(). */
  402.  
  403. static void cirrus_initializemode( unsigned char *moderegs,
  404. ModeTiming *modetiming, ModeInfo *modeinfo) {
  405.  
  406.     /* Get current values. */
  407.     cirrus_saveregs(moderegs);
  408.  
  409.     /* Set up the standard VGA registers for a generic SVGA. */
  410.     setup_VGA_registers(moderegs, modetiming, modeinfo);
  411.  
  412.     /* Set up the extended register values, including modifications */
  413.     /* of standard VGA registers. */
  414.  
  415. /* Graphics */
  416.     moderegs[CIRRUS_GRAPHICSOFFSET1] = 0;    /* Reset banks. */
  417.     moderegs[CIRRUS_GRAPHICSOFFSET2] = 0;
  418.     moderegs[CIRRUS_GRB] = 0;    /* 0x01 enables dual banking. */
  419.     if (cirrus_memory > 1024)
  420.         /* Enable 16K granularity. */
  421.         moderegs[CIRRUS_GRB] |= 0x20;
  422.     moderegs[VGA_SR2] = 0xFF;    /* Plane mask */
  423.  
  424. /* CRTC */
  425.     if (modetiming->VTotal >= 1024 && !(modetiming->flags & INTERLACED))
  426.         /*
  427.          * Double the vertical timing. Used for 1280x1024 NI.
  428.          * The CrtcVTimings have already been adjusted
  429.          * by getmodetiming() because of the GREATER_1024_DIVIDE_VERT
  430.          * flag.
  431.          */
  432.         moderegs[VGA_CR17] |= 0x04;
  433.     moderegs[CIRRUS_CR1B] = 0x22;
  434.     if (cirrus_chiptype == CLGD5434)
  435.         /* Clear display start bit 19. */
  436.         SETBITS(moderegs[CIRRUS_CR1D], 0x80, 0);
  437.     /* CRTC timing overflows. */
  438.     moderegs[CIRRUS_CR1A] = 0;
  439.     SETBITSFROMVALUE(moderegs[CIRRUS_CR1A], 0xC0,
  440.         modetiming->CrtcVSyncStart + 1, 0x300);
  441.     SETBITSFROMVALUE(moderegs[CIRRUS_CR1A], 0x30,
  442.         modetiming->CrtcHSyncEnd, (0xC0 << 3));
  443.     moderegs[CIRRUS_CR19] = 0;    /* Interlaced end. */
  444.     if (modetiming->flags & INTERLACED) {
  445.         moderegs[CIRRUS_CR19] =
  446.             ((modetiming->CrtcHTotal / 8) - 5) / 2;
  447.         moderegs[CIRRUS_CR1A] |= 0x01;
  448.     }
  449.  
  450. /* Scanline offset */
  451.     if (modeinfo->bytesPerPixel == 4) {
  452.         /* At 32bpp the chip does an extra multiplication by two. */
  453.         moderegs[VGA_SCANLINEOFFSET] = modeinfo->lineWidth >> 4;
  454.         SETBITSFROMVALUE(moderegs[CIRRUS_CR1B], 0x10,
  455.             modeinfo->lineWidth, 0x1000);
  456.     }
  457.     else
  458.     if (modeinfo->bitsPerPixel == 4)
  459.         /* 16 color mode (planar). */
  460.         moderegs[VGA_SCANLINEOFFSET] = modeinfo->lineWidth >> 1;
  461.     else {
  462.         moderegs[VGA_SCANLINEOFFSET] = modeinfo->lineWidth >> 3;
  463.         SETBITSFROMVALUE(moderegs[CIRRUS_CR1B], 0x10,
  464.              modeinfo->lineWidth, 0x800);
  465.     }
  466.  
  467. /* Clocking */
  468.     moderegs[VGA_MISCOUTPUT] |= 0x0C;    /* Use VCLK3. */
  469.     moderegs[CIRRUS_VCLK3NUMERATOR] =
  470.         fixed_clock_numerator[modetiming->selectedClockNo];
  471.     moderegs[CIRRUS_VCLK3DENOMINATOR] =
  472.         fixed_clock_denominator[modetiming->selectedClockNo];
  473.  
  474. /* DAC register and Sequencer Mode */
  475.     {
  476.     unsigned char DAC, SR7;
  477.     DAC = 0x00;
  478.     SR7 = 0x00;
  479.     if (modeinfo->bytesPerPixel > 0)
  480.         SR7 = 0x01;    /* Packed-pixel mode. */
  481.     if (modeinfo->bytesPerPixel == 2) {
  482.         int rgbmode;
  483.         rgbmode = 0;    /* 5-5-5 RGB. */
  484.         if (modeinfo->colorBits == 16)
  485.             rgbmode = 1;    /* Add one for 5-6-5 RGB. */
  486.         if (cirrus_chiptype >= CLGD5426) {
  487.             /* Pixel clock (double edge) mode. */
  488.             DAC = 0xD0 + rgbmode;
  489.             SR7 = 0x07;
  490.         }
  491.         else {
  492.             /* Single-edge (double VCLK). */
  493.             DAC = 0xF0 + rgbmode;
  494.             SR7 = 0x03;
  495.         }
  496.     }
  497.     if (modeinfo->bytesPerPixel >= 3) {
  498.         /* Set 8-8-8 RGB mode. */
  499.         DAC = 0xE5;
  500.         SR7 = 0x05;
  501.         if (modeinfo->bytesPerPixel == 4)
  502.             SR7 = 0x09;
  503.     }
  504. #ifdef SUPPORT_5434_PALETTE_CLOCK_DOUBLING
  505.     if (modeinfo->bytesPerPixel == 1 && (modetiming->flags & HADJUSTED)) {
  506.         /* Palette clock doubling mode on 5434 8bpp. */
  507.         DAC = 0x4A;
  508.         SR7 = 0x07;
  509.     }
  510. #endif
  511.     moderegs[CIRRUS_HIDDENDAC] = DAC;
  512.     moderegs[CIRRUS_SR7] = SR7;
  513.     }
  514.  
  515. /* DRAM control and CRT FIFO */
  516.     if (cirrus_chiptype >= CLGD5422)
  517.         /* Enable large CRT FIFO. */
  518.         moderegs[CIRRUS_DRAMCONTROL] |= 0x20;
  519.     if (cirrus_memory == 2048 && cirrus_chiptype <= CLGD5429)
  520.         /* Enable DRAM Bank Select. */
  521.         moderegs[CIRRUS_DRAMCONTROL] |= 0x80;
  522.     if (cirrus_chiptype >= CLGD5422) {
  523.         /* CRT FIFO threshold setting. */
  524.         unsigned char threshold;
  525.         threshold = 8;
  526.         if (cirrus_chiptype == CLGD5434)
  527.             threshold = 1;
  528.         /* XXX Needs more elaborate setting. */
  529.         SETBITS(moderegs[CIRRUS_PERFTUNING], 0x0F, threshold);
  530.     }
  531.     if (CHIP_HAS_MCLK_REGISTER())
  532.         if (programmedMCLK != actualMCLK
  533.         && modeinfo->bytesPerPixel > 0)
  534.             /* Program higher MCLK for packed-pixel modes. */
  535.             moderegs[CIRRUS_MCLKREGISTER] = programmedMCLK;
  536. }
  537.  
  538.  
  539. /* This is the clock mapping function that is put in the CardSpecs. */
  540.  
  541. static int cirrus_map_clock( int bpp, int pixelclock ) {
  542.     if (bpp == 24)
  543.         /* All chips need a tripled clock for 24bpp. */
  544.         return pixelclock * 3;
  545.     if (bpp == 16 && cirrus_chiptype <= CLGD5424)
  546.         /* The 5422/24 need to use a doubled clock. */
  547.         return pixelclock * 2;
  548.     return pixelclock;
  549. }
  550.  
  551. /* This is the horizontal CRTC mapping function in the CardSpecs. */
  552.  
  553. static int cirrus_map_horizontal_crtc( int bpp, int pixelclock, int htiming ) {
  554. #ifdef ALWAYS_USE_5434_PALETTE_CLOCK_DOUBLING
  555.     if (bpp == 8 && cirrus_chiptype == CLGD5434)
  556. #else    
  557.     if (bpp == 8 && cirrus_chiptype == CLGD5434 && pixelclock > 86000)
  558. #endif
  559.         /* 5434 palette clock doubling mode; divide CRTC by 2. */
  560.         return htiming / 2;
  561.     /* Otherwise, don't change. */
  562.     return htiming;
  563. }
  564.  
  565. static void init_acceleration_specs_for_mode( AccelSpecs *accelspecs, int bpp,
  566. int width_in_pixels );
  567.  
  568. static int cirrus_setmode( int mode, int prv_mode ) {
  569.     unsigned char *moderegs;
  570.     ModeTiming *modetiming;
  571.     ModeInfo *modeinfo;
  572.  
  573.     if ((mode < G640x480x256 && mode != G320x200x256)
  574.     || mode == G720x348x2) {
  575.         clear_accelspecs(driverspecs->accelspecs);
  576.         /* Let the standard VGA driver set standard VGA modes */
  577.         /* But first reset an Cirrus extended register that */
  578.         /* an old XFree86 Trident probe corrupts. */
  579.         outw(0x3d4, 0x4a0b);
  580.         return vga_driverspecs.setmode(mode);
  581.     }
  582.     if (!cirrus_modeavailable(mode))
  583.             return 1;
  584.  
  585.     modeinfo = createModeInfoStructureForSvgalibMode(mode);
  586.  
  587.     modetiming = malloc(sizeof(ModeTiming));
  588.     if (getmodetiming(modetiming, modeinfo, cardspecs)) {
  589.         free(modetiming);
  590.         free(modeinfo);
  591.         return 1;
  592.     }
  593.  
  594.     moderegs = malloc(CIRRUS_TOTAL_REGS);
  595.  
  596.     cirrus_initializemode(moderegs, modetiming, modeinfo);
  597.     free(modetiming);
  598.  
  599.     __vga_setregs(moderegs);    /* Set standard regs. */
  600.     cirrus_setregs(moderegs, mode);    /* Set extended regs. */
  601.     free(moderegs);
  602.  
  603.     InitializeAcceleratorInterface(modeinfo);
  604.  
  605.     init_acceleration_specs_for_mode(driverspecs->accelspecs,
  606.         modeinfo->bitsPerPixel,
  607.         modeinfo->lineWidth / modeinfo->bytesPerPixel);
  608.  
  609.     cirrusaccel_init(driverspecs->accelspecs,
  610.         modeinfo->bitsPerPixel,
  611.         modeinfo->lineWidth / modeinfo->bytesPerPixel);
  612.  
  613.     free(modeinfo);
  614.     return 0;
  615. }
  616.  
  617.  
  618. /* Unlock chipset-specific registers */
  619.  
  620. static void cirrus_unlock() {
  621.     int vgaIOBase, temp;
  622.     
  623.                 /* Are we Mono or Color? */
  624.            vgaIOBase = (inb(0x3CC) & 0x01) ? 0x3D0 : 0x3B0;
  625.  
  626.            outb(0x3C4,0x06);
  627.            outb(0x3C5,0x12);    /* unlock cirrus special */
  628.  
  629.                 /* Put the Vert. Retrace End Reg in temp */
  630.  
  631.            outb(vgaIOBase + 4, 0x11); temp = inb(vgaIOBase + 5);
  632.  
  633.                 /* Put it back with PR bit set to 0 */
  634.                 /* This unprotects the 0-7 CRTC regs so */
  635.                 /* they can be modified, i.e. we can set */
  636.                 /* the timing. */
  637.  
  638.            outb(vgaIOBase + 5, temp & 0x7F);
  639. }
  640.  
  641.  
  642. /* Relock chipset-specific registers */
  643. /* (currently not used) */
  644.  
  645. static void cirrus_lock() {
  646.     outb(0x3C4,0x06);
  647.     outb(0x3C5,0x0F);     /* relock cirrus special */
  648. }
  649.  
  650.  
  651. /* Indentify chipset, initialize and return non-zero if detected */
  652.  
  653. static int cirrus_test() {
  654.     int oldlockreg;
  655.     int lockreg;
  656.  
  657.     outb(0x3c4, 0x06);
  658.     oldlockreg = inb(0x3c5);
  659.  
  660.     cirrus_unlock();
  661.  
  662.       /* If it's a Cirrus at all, we should be */
  663.       /* able to read back the lock register */
  664.       
  665.       outb(0x3C4,0x06);
  666.       lockreg = inb(0x3C5);
  667.       
  668.       /* Ok, if it's not 0x12, we're not a Cirrus542X. */
  669.     if (lockreg != 0x12) {
  670.         outb(0x3c4, 0x06);
  671.         outb(0x3c5, oldlockreg);
  672.         return 0;
  673.     }
  674.     
  675.     /* The above check seems to be weak, so we also check the chip ID. */
  676.     
  677.     outb(CRT_I, 0x27);
  678.     switch (inb(CRT_D) >> 2) {
  679.         case 0x22 : 
  680.         case 0x23 :
  681.         case 0x24 :
  682.         case 0x25 :
  683.         case 0x26 :
  684.         case 0x27 :     /* 5429 */
  685.         case 0x28 :    /* 5430 */
  686.         case 0x2A :    /* 5434 */
  687.             break;
  688.         default :
  689.             outb(0x3c4, 0x06);
  690.             outb(0x3c5, oldlockreg);
  691.             return 0;
  692.     }
  693.  
  694.     if (cirrus_init(0, 0, 0))
  695.         return 0;    /* failure */
  696.     return 1;
  697. }
  698.  
  699.  
  700. /* Bank switching function -- set 64K page number */
  701.  
  702. static void cirrus_setpage_2M( unsigned page ) {
  703.     /* Cirrus banking register has been set to 16K granularity */
  704.     outw(0x3ce, (page << 10) + 0x09);
  705. }
  706.  
  707. static void cirrus_setpage( unsigned page ) {
  708.     /* default 4K granularity */
  709.     outw(0x3ce, (page << 12) + 0x09);
  710. }
  711.  
  712.  
  713. /* No r/w paging */
  714. static void cirrus_setrdpage(unsigned page) { }
  715. static void cirrus_setwrpage(unsigned page) { }
  716.  
  717.  
  718. /* Set display start address (not for 16 color modes) */
  719. /* Cirrus supports any address in video memory (up to 2Mb) */
  720.  
  721. static void cirrus_setdisplaystart( int address ) {
  722.     outw(0x3d4, 0x0d + ((address >> 2) & 0x00ff) * 256);    /* sa2-sa9 */
  723.     outw(0x3d4, 0x0c + ((address >> 2) & 0xff00));        /* sa10-sa17 */
  724.     inb(0x3da);            /* set ATC to addressing mode */
  725.     outb(0x3c0, 0x13 + 0x20);    /* select ATC reg 0x13 */
  726.     /* Cirrus specific bits 0,1 and 18,19,20: */
  727.     outb(0x3c0, (inb(0x3c1) & 0xf0) | (address & 3));
  728.         /* write sa0-1 to bits 0-1; other cards use bits 1-2 */
  729.     outb(0x3d4, 0x1b);
  730.     outb(0x3d5, (inb(0x3d5) & 0xf2) 
  731.         | ((address & 0x40000) >> 18)    /* sa18: write to bit 0 */
  732.         | ((address & 0x80000) >> 17)    /* sa19: write to bit 2 */
  733.         | ((address & 0x100000) >> 17)); /* sa20: write to bit 3 */
  734.     outb(0x3d4, 0x1d);
  735.     if (cirrus_memory > 2048)
  736.         outb(0x3d5, (inb(0x3d5) & 0x7f)
  737.             | ((address & 0x200000) >> 14)); /* sa21: write to bit 7 */
  738. }
  739.  
  740.  
  741. /* Set logical scanline length (usually multiple of 8) */
  742. /* Cirrus supports multiples of 8, up to 4088 */
  743.  
  744. static void cirrus_setlogicalwidth( int width ) { 
  745.     outw(0x3d4, 0x13 + (width >> 3) * 256);    /* lw3-lw11 */
  746.     outb(0x3d4, 0x1b);
  747.     outb(0x3d5, (inb(0x3d5) & 0xef) | ((width & 0x800) >> 7));
  748.         /* write lw12 to bit 4 of Sequencer reg. 0x1b */
  749. }
  750.  
  751. static void cirrus_setlinear(int addr)
  752. {
  753.     int val;
  754.     outb(0x3c4, 0x07);
  755.     val = inb(0x3c5);
  756.     outb(0x3c5, (val & 0x0f) | (addr << 4));
  757. }
  758.  
  759. static int cirrus_linear( int op, int param ) {
  760.     if (op == LINEAR_ENABLE) {
  761.         cirrus_setlinear(0xE);
  762.         return 0;
  763.     }
  764.     if (op == LINEAR_DISABLE) {
  765.         cirrus_setlinear(0);
  766.         return 0;
  767.     }
  768.     if (cirrus_chiptype >= CLGD5424 && cirrus_chiptype <= CLGD5429) {
  769.         if (op == LINEAR_QUERY_BASE) {
  770.             if (param == 0)
  771.                 return 0xE00000;    /* 14MB */
  772.     /*
  773.      * Trying 64MB on a system with 16MB of memory is unsafe if the
  774.      * card maps at 14MB. 14 MB was not attempted because of the
  775.      * system memory check in vga_setlinearaddressing(). However,
  776.      * linear addressing is enabled when looking at 64MB, causing a
  777.      * clash between video card and system memory at 14MB.
  778.      */
  779.              if (__svgalib_physmem() <= 13 * 1024 * 1024) {
  780.                 if (param == 1)
  781.                     return 0x4000000;    /* 64MB */
  782.                 if (param == 2)    
  783.                     return 0x4E00000;    /* 78MB */
  784.                 if (param == 3)
  785.                     return 0x2000000;    /* 32MB */
  786.             }
  787.             return -1;
  788.         }
  789.     }
  790.     if (cirrus_chiptype >= CLGD5430) {
  791.         if (op == LINEAR_QUERY_BASE) {
  792.             if (param == 0)
  793.                 return 0x04000000;    /* 64MB */
  794.             if (param == 1)    
  795.                 return 0x80000000;    /* 2048MB */
  796.             if (param == 2)
  797.                 return 0x02000000;    /* 32MB */
  798.             if (param == 3)
  799.                 return 0x08000000;    /* 128MB */
  800.             /* While we're busy, try some common PCI */
  801.             /* motherboard-configured addresses as well. */
  802.             /* We only read, so should be safe. */
  803.             if (param == 4)
  804.                 return 0xA0000000;
  805.             if (param == 5)
  806.                 return 0xA8000000;
  807.             if (param == 6)
  808.                 return 0xF0000000;
  809.             return -1;
  810.         }
  811.     }
  812.  
  813.     if (op == LINEAR_QUERY_RANGE || op == LINEAR_QUERY_GRANULARITY)
  814.         return 0;    /* No granularity or range. */
  815.     else
  816.         return -1;    /* Unknown function. */
  817. }
  818.  
  819.  
  820. /* Function table (exported) */
  821.  
  822. static int cirrus_bitblt( int, int, int, int, int );
  823. static int cirrus_imageblt( unsigned *, int, int, int, int );
  824. static int cirrus_fillblt( int, int, int, int, int );
  825. static int cirrus_hlinelistblt( int, int, int *, int *, int, int );
  826. static int cirrus_bltwait();
  827.  
  828. DriverSpecs cirrus_driverspecs = {
  829.     cirrus_saveregs,
  830.     cirrus_setregs,
  831.     cirrus_unlock,
  832.     cirrus_lock,
  833.     cirrus_test,
  834.     cirrus_init,
  835.     cirrus_setpage,
  836.     cirrus_setrdpage,
  837.     cirrus_setwrpage,
  838.     cirrus_setmode,
  839.     cirrus_modeavailable,
  840.     cirrus_setdisplaystart,
  841.     cirrus_setlogicalwidth,
  842.     cirrus_getmodeinfo,
  843.     cirrus_bitblt,
  844.     cirrus_imageblt,
  845.     cirrus_fillblt,
  846.     cirrus_hlinelistblt,
  847.     cirrus_bltwait,
  848.     0,    /* ext_set */
  849.     0,    /* accel */
  850.     cirrus_linear,
  851.     0    /* accelspecs, filled in during init. */
  852. };
  853.  
  854.  
  855. /* Initialize chipset (called after detection) */
  856.  
  857. static char *cirrus_chipname[] = {
  858.     "5420", "5420-75QC-B", "5422", "5422-80QC-C", "5424", "5426", "5428",
  859.     "5429",    "5430", "5434"
  860. };
  861.  
  862. static int cirrus_init( int force, int par1, int par2 ) {
  863.     unsigned char v;
  864.     cirrus_unlock();
  865.     if (force) {
  866.         cirrus_memory = par1;
  867.         cirrus_chiptype = par2;
  868.     }
  869.     else {
  870.         unsigned char partstatus;
  871.         outb(CRT_I, 0x27);
  872.         cirrus_chiptype = inb(CRT_D) >> 2;
  873.         cirrus_chiprev = 0;
  874.         partstatus = inCR(0x25);
  875.         switch (cirrus_chiptype) {
  876.             case 0x22 :
  877.                 cirrus_chiptype = CLGD5420;
  878. #if 0
  879.                 /* Check for CL-GD5420-75QC-B. */
  880.                 /* It has a Hidden-DAC register. */
  881.                 outb(0x3C6, 0x00);
  882.                 outb(0x3C6, 0xFF);
  883.                 inb(0x3C6); inb(0x3c6); inb(0x3C6); inb(0x3C6);
  884.                 if (inb(0x3C6) != 0xFF)
  885.                     cirrus_chiptype = CLGD5420B; break;
  886.                 break;
  887. #endif
  888.             case 0x23 : cirrus_chiptype = CLGD5422; break;
  889.             case 0x24 : cirrus_chiptype = CLGD5426; break;
  890.             case 0x25 :
  891.                 cirrus_chiptype = CLGD5424;
  892.                 /*
  893.                  * Some CL-GD5422's ID as CL-GD5424.
  894.                  * Check for writability of GRC.
  895.                  */
  896.                 v = inGR(0x0C);
  897.                 outGR(0x0C, 0x55);
  898.                 if (inGR(0x0C) != 0x55)
  899.                     cirrus_chiptype = CLGD5422;
  900.                 outGR(0x0C, v);
  901.                 break;
  902.             case 0x26 : cirrus_chiptype = CLGD5428; break;
  903.             case 0x27 : cirrus_chiptype = CLGD5429; break;
  904.             case 0x28 : cirrus_chiptype = CLGD5430; break;
  905.             case 0x2A :
  906.                 cirrus_chiptype = CLGD5434;
  907.                 if ((partstatus & 0xC0) == 0xC0)
  908.                     /* Rev. E, can do 60 MHz MCLK. */
  909.                     cirrus_chiprev = 1;
  910.                 break;
  911.             default :
  912.                 printf("Unknown Cirrus chip %2x.\n",
  913.                     cirrus_chiptype);
  914.                 return -1;
  915.         }
  916.  
  917. #if 0
  918.         if (cirrus_chiptype == CLGD5422) {
  919.             /* Rev. C has programmable MCLK register; */
  920.             /* check for it. */
  921.             /* This check is wrong. */
  922.             if (inSR(0x1F) != 0xFF)
  923.                 cirrus_chiptype = CLGD5422C;
  924.         }
  925. #endif
  926.  
  927.         /* Now determine the amount of memory. */
  928.         outb(0x3c4, 0x0a);    /* read memory register */
  929.         /* This depends on the BIOS having set a scratch register. */
  930.         v = inb(0x3c5);
  931.         cirrus_memory = 256 << ((v >> 3) & 3);
  932.  
  933.         /* Determine memory the correct way for the 543x, and
  934.          * for the 542x if the amount seems incorrect. */
  935.         if (cirrus_chiptype >= CLGD5430 || (cirrus_memory <= 256
  936.         && cirrus_chiptype != CLGD5420)) {
  937.             unsigned char SRF;
  938.             cirrus_memory = 512;
  939.             outb(0x3c4, 0x0f);
  940.             SRF = inb(0x3c5);
  941.             if (SRF & 0x10)
  942.                 /* 32-bit DRAM bus. */
  943.                 cirrus_memory *= 2;
  944.               if ((SRF & 0x18) == 0x18)
  945.                   /* 64-bit DRAM data bus width; assume 2MB. */
  946.                   /* Also indicates 2MB memory on the 5430. */
  947.                   cirrus_memory *= 2;
  948.               if (cirrus_chiptype != CLGD5430 && (SRF & 0x80))
  949.                   /* If DRAM bank switching is enabled, there */
  950.                   /* must be twice as much memory installed. */
  951.                   /* (4MB on the 5434) */
  952.                   cirrus_memory *= 2;
  953.         }
  954.     }
  955.     if (__svgalib_driver_report) {
  956.         printf("Using Cirrus Logic GD542x/3x driver (%s, %dK).\n",
  957.             cirrus_chipname[cirrus_chiptype], cirrus_memory);
  958.     }
  959.  
  960.     if (CHIP_HAS_MCLK_REGISTER())
  961.         actualMCLK = inSR(0x1F) & 0x3F;
  962.     else {
  963.         static unsigned char fixedMCLK[4] = { 0x1c, 0x19, 0x17, 0x15 };
  964.         actualMCLK = fixedMCLK[inSR(0x0F) & 3];
  965.     }
  966.     programmedMCLK = actualMCLK;
  967.     if (cirrus_chiptype == CLGD5434 && cirrus_chiprev > 0)
  968.         /* 5434 rev. E+ supports 60 MHz in graphics modes. */
  969.         programmedMCLK = 0x22;
  970.     DRAMbandwidth = 14318 * (int)programmedMCLK / 16;
  971.     if (cirrus_memory >= 512)
  972.         /* At least 16-bit DRAM bus. */
  973.         DRAMbandwidth *= 2;
  974.     if (cirrus_memory >= 1024 && CHIP_HAS_32BIT_DRAM_BUS())
  975.         /* At least 32-bit DRAM bus. */
  976.         DRAMbandwidth *= 2;
  977.     if (cirrus_memory >= 2048 && CHIP_HAS_64BIT_DRAM_BUS())    
  978.         /* 64-bit DRAM bus. */
  979.         DRAMbandwidth *= 2;
  980.          /*
  981.           * Calculate highest acceptable DRAM bandwidth to be taken up
  982.           * by screen refresh. Satisfies
  983.           *    total bandwidth >= refresh bandwidth * 1.1
  984.           */
  985.          DRAMbandwidthLimit = (DRAMbandwidth * 10) / 11;
  986.  
  987. /* begin: Initialize card specs. */
  988.     cardspecs = malloc(sizeof(CardSpecs));
  989.     cardspecs->videoMemory = cirrus_memory;
  990.     /*
  991.      * First determine clock limits for the chip (DAC), then
  992.      * adjust them according to the available DRAM bandwidth.
  993.      * For 32-bit DRAM cards the 16bpp clock limit is initially
  994.      * set very high, but they are cut down by the DRAM bandwidth
  995.      * check.
  996.      */
  997.     cardspecs->maxPixelClock4bpp = 75000;    /* 5420 */
  998.     cardspecs->maxPixelClock8bpp = 45000;    /* 5420 */
  999.     cardspecs->maxPixelClock16bpp = 0;    /* 5420 */
  1000.     cardspecs->maxPixelClock24bpp = 0;
  1001.     cardspecs->maxPixelClock32bpp = 0;
  1002.     if (cirrus_chiptype == CLGD5420B) {
  1003.         /*
  1004.          * CL-GD5420-75QC-B
  1005.          * Deviating chip, may be used in cheap ISA cards.
  1006.          * 32-bit DRAM bus and Truecolor DAC but cannot do
  1007.          * LUT > 45 MHz, and has no (less?) acceleration.
  1008.          */
  1009.         cardspecs->maxPixelClock16bpp = 75000 / 2;
  1010.         cardspecs->maxPixelClock24bpp = 25175;
  1011.     }
  1012.     if (cirrus_chiptype >= CLGD5422) {
  1013.         /* 5422/24/26/28 have VCLK spec of 80 MHz. */
  1014.         cardspecs->maxPixelClock4bpp = 80000;
  1015.         cardspecs->maxPixelClock8bpp = 80000;
  1016.         if (cirrus_chiptype >= CLGD5426)
  1017.             /* DRAM bandwidth will be limiting factor. */
  1018.             cardspecs->maxPixelClock16bpp = 80000;
  1019.         else
  1020.             /* Clock / 2 16bpp requires 32-bit DRAM bus. */
  1021.             if (cirrus_memory >= 1024)
  1022.                 cardspecs->maxPixelClock16bpp = 80000 / 2;
  1023.         /* Clock / 3 24bpp requires 32-bit DRAM bus. */
  1024.         if (cirrus_memory >= 1024)
  1025.             cardspecs->maxPixelClock24bpp = 80000 / 3;
  1026.     }
  1027.     if (cirrus_chiptype >= CLGD5429) {
  1028.         /* 5429, 5430, 5434 have VCLK spec of 86 MHz. */
  1029.         cardspecs->maxPixelClock4bpp = 86000;
  1030.         cardspecs->maxPixelClock8bpp = 86000;
  1031.         cardspecs->maxPixelClock16bpp = 86000;
  1032.         if (cirrus_memory >= 1024)
  1033.             cardspecs->maxPixelClock24bpp = 86000 / 3;
  1034.     }
  1035.     if (cirrus_chiptype >= CLGD5434) {
  1036. #ifdef SUPPORT_5434_PALETTE_CLOCK_DOUBLING
  1037.         cardspecs->maxPixelClock8bpp = 108300;
  1038. #endif
  1039.         if (cirrus_memory >= 2048)
  1040.             /* 32bpp requires 64-bit DRAM bus. */
  1041.             cardspecs->maxPixelClock32bpp = 86000;
  1042.     }
  1043.     cardspecs->maxPixelClock8bpp = min(cardspecs->maxPixelClock8bpp,
  1044.         DRAMbandwidthLimit);
  1045.     cardspecs->maxPixelClock16bpp = min(cardspecs->maxPixelClock16bpp,
  1046.         DRAMbandwidthLimit / 2);
  1047.     cardspecs->maxPixelClock24bpp = min(cardspecs->maxPixelClock24bpp,
  1048.         DRAMbandwidthLimit / 3);
  1049.     cardspecs->maxPixelClock32bpp = min(cardspecs->maxPixelClock32bpp,
  1050.         DRAMbandwidthLimit / 4);
  1051.     cardspecs->flags = INTERLACE_DIVIDE_VERT | GREATER_1024_DIVIDE_VERT;
  1052.     /* Initialize clocks (only fixed set for now). */
  1053.     cardspecs->nClocks = NU_FIXED_CLOCKS;
  1054.     cardspecs->clocks = cirrus_fixed_clocks;
  1055.     cardspecs->mapClock = cirrus_map_clock;
  1056.     cardspecs->mapHorizontalCrtc = cirrus_map_horizontal_crtc;
  1057.     cardspecs->maxHorizontalCrtc = 2040;
  1058.     /* Disable 16-color SVGA modes (don't work correctly). */
  1059.     cardspecs->maxPixelClock4bpp = 0;
  1060. /* end: Initialize card specs. */
  1061.  
  1062. #if 0
  1063. /* begin: Initialize driver options. */
  1064.     register_option(5434_VLB_ZERO_WAITSTATE);
  1065.     register_option(50MHZ_MCLK);
  1066.     register_option(55MHZ_MCLK);
  1067.     register_option(60MHZ_MCLK);
  1068.     register_option(542X_VLB_NORMAL_WAITSTATES);
  1069.     register_option(CRT_FIFO_CONSERVATIVE);
  1070.     register_option(CRT_FIFO_AGGRESSIVE);
  1071.     register_option(NO_ACCELERATION);
  1072.     register_option(NO_MMIO);
  1073. /* end: Initialize driver options. */
  1074. #endif
  1075.  
  1076. /* Initialize accelspecs structure. */
  1077.     cirrus_driverspecs.accelspecs = malloc(sizeof(AccelSpecs));
  1078.     cirrus_driverspecs.accelspecs->flags = ACCELERATE_ANY_LINEWIDTH;
  1079.     if (cirrus_chiptype >= CLGD5429) {
  1080.         /* Map memory-mapped I/O register space. */
  1081.         mmio_base = valloc(32 * 1024);
  1082.         mmap(mmio_base, 32 * 1024, PROT_WRITE, MAP_FIXED | MAP_SHARED,
  1083.             __svgalib_mem_fd, 0xB8000);
  1084.     }
  1085.  
  1086.     /* Set up the correct paging routine */
  1087.     if (cirrus_memory >= 2048)
  1088.         cirrus_driverspecs.setpage = 
  1089.             cirrus_setpage_2M;
  1090.  
  1091.     driverspecs = &cirrus_driverspecs;
  1092.  
  1093.     return 0;
  1094. }
  1095.  
  1096.  
  1097.  
  1098. /*     Some information on the accelerated features of the 5426,
  1099.     derived from the Databook.
  1100.     
  1101.     port    index
  1102.  
  1103.     Addresses have 21 bits (2Mb of memory).
  1104.     0x3ce,    0x28    bits 0-7 of the destination address
  1105.     0x3ce,  0x29    bits 8-15
  1106.     0x3ce,    0x2a    bits 16-20
  1107.  
  1108.     0x3ce,    0x2c    bits 0-7 of the source address
  1109.     0x3ce,    0x2d    bits 8-15
  1110.     0x3ce,    0x2e    bits 16-20
  1111.  
  1112.     Maximum pitch is 4095.
  1113.     0x3ce,    0x24    bits 0-7 of the destination pitch (screen width)
  1114.     0x3ce,    0x25    bits 8-11
  1115.     
  1116.     0x3ce,    0x26    bits 0-7 of the source pitch (screen width)
  1117.     0x3ce,    0x27    bits 8-11
  1118.     
  1119.     Maximum width is 2047.
  1120.     0x3ce,    0x20    bits 0-7 of the box width - 1
  1121.     0x3ce,    0x21    bits 8-10
  1122.     
  1123.     Maximum height is 1023.
  1124.     0x3ce,    0x22    bits 0-7 of the box height - 1
  1125.     0x3ce,    0x23    bits 8-9
  1126.  
  1127.     0x3ce,    0x30    BLT mode
  1128.             bit 0: direction (0 = down, 1 = up)
  1129.             bit 1: destination
  1130.             bit 2: source (0 = video memory, 1 = system memory)
  1131.             bit 3: enable transparency compare
  1132.             bit 4: 16-bit color expand/transparency
  1133.             bit 6: 8x8 pattern copy
  1134.             bit 7: enable color expand
  1135.  
  1136.         0x31    BLT status
  1137.             bit 0: busy
  1138.             bit 1: start operation (1)/suspend (0)
  1139.             bit 2: reset
  1140.             bit 3: set while blit busy/suspended
  1141.  
  1142.         0x32    BLT raster operation
  1143.             0x00    black
  1144.             0x01    white
  1145.             0x0d    copy source
  1146.             0xd0    copy inverted source
  1147.             0x0b    invert destination
  1148.             0x05    logical AND
  1149.             0x6d    logical OR (paint)
  1150.             0x59    XOR
  1151.  
  1152.         0x34    BLT transparent color
  1153.         0x35    high byte
  1154.  
  1155.     0x3ce,  0x00    background color (for color expansion)
  1156.     0x3ce,  0x01    foreground color
  1157.     0x3ce,  0x10    high byte of background color for 16-bit pixels
  1158.     0x3ce,  0x11    high byte of foreground color
  1159.  
  1160.     0x3ce,    0x0b    bit 1: enable BY8 addressing
  1161.     0x3c4,    0x02    8-bit plane mask for BY8 (corresponds to 8 pixels)
  1162.             (write mode 1, 4, 5)
  1163.     0x3c5,  0x05    bits 0-2: VGA write mode
  1164.             extended write mode 4: write up to 8 pixels in
  1165.                 foreground color (BY8)
  1166.             extended write mode 5: write 8 pixels in foreground/
  1167.                 background color (BY8)
  1168.             This may also work in normal non-BY8 packed-pixel mode.
  1169.  
  1170.     When doing blits from system memory to video memory, pixel data
  1171.     can apparently be written to any video address in 16-bit words, with
  1172.     the each scanline padded to 4-byte alignment. This is handy because
  1173.     the chip handles line transitions and alignment automatically (and
  1174.     can do, for example, masking).
  1175.  
  1176.     The pattern copy requires an 8x8 pattern (64 pixels) at the source
  1177.     address in video memory, and fills a box with specified size and 
  1178.     destination address with the pattern. This is in fact the way to do
  1179.     solid fills.
  1180.     
  1181.     mode            pattern
  1182.     Color Expansion        8 bytes (monochrome bitmap)
  1183.     8-bit pixels        64 bytes
  1184.     16-bit pixels        128 bytes
  1185.  
  1186. */
  1187.  
  1188.  
  1189. static int cirrus_bltwait() {
  1190.     outb(0x3ce, 0x31);
  1191.     while (inb(0x3cf) & 1);        /* wait until finished */
  1192.     return 0;
  1193. }
  1194.  
  1195. static int cirrus_bitblt( int srcaddr, int destaddr, int w, int h, 
  1196. int pitch ) {
  1197.         int blt_direction = 0x0000;
  1198.  
  1199.     w--;
  1200.     h--;
  1201.  
  1202. /*
  1203.         if the blit goes downwards, we have to start from lower right
  1204.         corner instead of upper left corner to cope with overlapping regions
  1205. */
  1206.  
  1207.     if (destaddr > srcaddr) {
  1208.       srcaddr  += h*pitch + w;
  1209.       destaddr += h*pitch + w;
  1210.       blt_direction = 0x0100;
  1211.     }
  1212.  
  1213.     outw(0x3ce, 0x20 + (w << 8));        /* bits 0-7 of width */
  1214.     outw(0x3ce, 0x21 + (w & 0xff00));    /* bits 8-10 */
  1215.  
  1216.     outw(0x3ce, 0x22 + (h << 8));        /* bits 0-7 of height */
  1217.     outw(0x3ce, 0x23 + (h & 0xff00));    /* bits 8-9 */
  1218.  
  1219.     outw(0x3ce, 0x24 + (pitch << 8));    /* bits 0-7 of dest. pitch */
  1220.     outw(0x3ce, 0x25 + (pitch & 0xff00));    /* bits 8-11 */
  1221.     outw(0x3ce, 0x26 + (pitch << 8));    /* source pitch */
  1222.     outw(0x3ce, 0x27 + (pitch & 0xff00));
  1223.  
  1224.     outw(0x3ce, 0x28 + (destaddr << 8));    /* bits 0-7 of dest. address */
  1225.     outw(0x3ce, 0x29 + (destaddr & 0xff00));      /* bits 8-15 */
  1226.     outw(0x3ce, 0x2a + ((destaddr & 0x1f0000) >> 8)); /* bits 16-20 */
  1227.  
  1228.     outw(0x3ce, 0x2c + (srcaddr << 8));    /* bits 0-7 of src address */
  1229.     outw(0x3ce, 0x2d + (srcaddr & 0xff00));         /* bits 8-15 */
  1230.     outw(0x3ce, 0x2e + ((srcaddr & 0x1f0000) >> 8)); /* bits 16-20 */
  1231.  
  1232.     outw(0x3ce, 0x30 + blt_direction);    /* normal blit */
  1233.     outw(0x3ce, 0x32 + 0x0d00);        /* operation: copy */
  1234.     outw(0x3ce, 0x31 + 0x0200);        /* start operation */
  1235.  
  1236.     return cirrus_bltwait();
  1237. }
  1238.  
  1239.  
  1240. static int cirrus_imageblt( unsigned *srcaddr, int destaddr, int w, int h, 
  1241. int pitch ) {
  1242.     int count;
  1243.     unsigned *base;
  1244.     
  1245.     w--;
  1246.     outw(0x3ce, 0x20 + (w << 8));        /* bits 0-7 of width */
  1247.     outw(0x3ce, 0x21 + (w & 0xff00));    /* bits 8-10 */
  1248.  
  1249.     h--;
  1250.     outw(0x3ce, 0x22 + (h << 8));        /* bits 0-7 of height */
  1251.     outw(0x3ce, 0x23 + (h & 0xff00));    /* bits 8-9 */
  1252.  
  1253.     outw(0x3ce, 0x24 + (pitch << 8));    /* bits 0-7 of dest. pitch */
  1254.     outw(0x3ce, 0x25 + (pitch & 0xff00));    /* bits 8-11 */
  1255.  
  1256.     /* source pitch not required */
  1257.  
  1258.     outw(0x3ce, 0x28 + (destaddr << 8));    /* bits 0-7 of dest. address */
  1259.     outw(0x3ce, 0x29 + (destaddr & 0xff00));      /* bits 8-15 */
  1260.     outw(0x3ce, 0x2a + ((destaddr & 0x1f0000) >> 8)); /* bits 16-20 */
  1261.  
  1262.     /* blit source address not required */
  1263.  
  1264.     outw(0x3ce, 0x30 + 0x0400);    /* from system memory */
  1265.     outw(0x3ce, 0x32 + 0x0d00);    /* operation: copy */
  1266.     outw(0x3ce, 0x31 + 0x0200);    /* start operation */
  1267.     
  1268.     w++;
  1269.     h++;
  1270.     count = (w * h + 3) / 4;    /* #longwords */
  1271.     /* This may not be quite right for the last few bytes */
  1272.  
  1273.     base = (unsigned *)(__svgalib_graph_mem + 4);
  1274.     
  1275. #define USE_ASM    
  1276.  
  1277.     {
  1278.     unsigned *srcp;
  1279.     unsigned *endp;
  1280.     srcp = srcaddr;
  1281.     endp = srcaddr + count;
  1282.     #ifdef USE_ASM
  1283.     while (srcp + 16 <= endp) {
  1284.         int t;    /* temp. storage only */ 
  1285.         asm(
  1286.             "movl (%1),%0\n\t"
  1287.             "movl %0,(%2)\n\t"
  1288.             "movl 4(%1),%0\n\t"
  1289.             "movl %0,(%2)\n\t"
  1290.             "movl 8(%1),%0\n\t"
  1291.             "movl %0,(%2)\n\t"
  1292.             "movl 12(%1),%0\n\t"
  1293.             "movl %0,(%2)\n\t"
  1294.             "movl 16(%1),%0\n\t"
  1295.             "movl %0,(%2)\n\t"
  1296.             "movl 20(%1),%0\n\t"
  1297.             "movl %0,(%2)\n\t"
  1298.             "movl 24(%1),%0\n\t"
  1299.             "movl %0,(%2)\n\t"
  1300.             "movl 28(%1),%0\n\t"
  1301.             "movl %0,(%2)\n\t"
  1302.             "movl 32(%1),%0\n\t"
  1303.             "movl %0,(%2)\n\t"
  1304.             "movl 36(%1),%0\n\t"
  1305.             "movl %0,(%2)\n\t"
  1306.             "movl 40(%1),%0\n\t"
  1307.             "movl %0,(%2)\n\t"
  1308.             "movl 44(%1),%0\n\t"
  1309.             "movl %0,(%2)\n\t"
  1310.             "movl 48(%1),%0\n\t"
  1311.             "movl %0,(%2)\n\t"
  1312.             "movl 52(%1),%0\n\t"
  1313.             "movl %0,(%2)\n\t"
  1314.             "movl 56(%1),%0\n\t"
  1315.             "movl %0,(%2)\n\t"
  1316.             "movl 60(%1),%0\n\t"
  1317.             "movl %0,(%2)\n\t"
  1318.             : : "r" (t), "r" (srcp), "r" (base)
  1319.         );
  1320.         srcp += 16;    /* add 16 * 4 to pointer */
  1321.     }
  1322.     #endif
  1323.     while (srcp < endp)
  1324.         *base = *(srcp++);
  1325.     }
  1326.  
  1327.     return cirrus_bltwait();
  1328. }
  1329.  
  1330.  
  1331. static int pattern = -1;
  1332.  
  1333. static int initializepattern() {
  1334.     int i;
  1335.     int v;
  1336. #if 0
  1337.     /* Write 8x8 monochrome pattern above claimed video memory. */
  1338.     v = VMEM;
  1339.     if (vga_claimvideomemory(VMEM + 8)) {
  1340.         printf("svgalib: Cannot allocate video memory for Cirrus fill pattern.\n");
  1341.         return 1;
  1342.     }
  1343.     pattern = v;
  1344. #else
  1345.     pattern = cirrus_memory * 1024 - 256;
  1346. #endif
  1347.     if (cirrus_inlinearmode())
  1348.         memset(vga_getgraphmem() + pattern, 0xff, 8);
  1349.     else {
  1350.         cirrus_driverspecs.setpage(pattern >> 16);
  1351.         memset(__svgalib_graph_mem + (pattern & 0xffff), 0xff, 8);
  1352.     }
  1353.     return 0;
  1354. }
  1355.  
  1356. static int cirrus_fillblt( int destaddr, int w, int h, int pitch, int c ) {
  1357.     int srcaddr;
  1358.  
  1359.     if (pattern == -1)
  1360.         if (initializepattern())
  1361.             return -1;
  1362.     
  1363.     srcaddr = pattern;
  1364.  
  1365.     outw(0x3ce, 0x2c + (srcaddr << 8));    /* bits 0-7 of src address */
  1366.     outw(0x3ce, 0x2d + (srcaddr & 0xff00));         /* bits 8-15 */
  1367.     outw(0x3ce, 0x2e + ((srcaddr & 0x1f0000) >> 8)); /* bits 16-20 */
  1368.  
  1369.     w--;
  1370.     outw(0x3ce, 0x20 + (w << 8));        /* bits 0-7 of width */
  1371.     outw(0x3ce, 0x21 + (w & 0xff00));    /* bits 8-10 */
  1372.  
  1373.     h--;
  1374.     outw(0x3ce, 0x22 + (h << 8));        /* bits 0-7 of height */
  1375.     outw(0x3ce, 0x23 + (h & 0xff00));    /* bits 8-9 */
  1376.  
  1377.     outw(0x3ce, 0x24 + (pitch << 8));    /* bits 0-7 of dest. pitch */
  1378.     outw(0x3ce, 0x25 + (pitch & 0xff00));    /* bits 8-11 */
  1379.  
  1380.     outw(0x3ce, 0x28 + (destaddr << 8));    /* bits 0-7 of dest. address */
  1381.     outw(0x3ce, 0x29 + (destaddr & 0xff00));      /* bits 8-15 */
  1382.     outw(0x3ce, 0x2a + ((destaddr & 0x1f0000) >> 8)); /* bits 16-20 */
  1383.  
  1384.     outw(0x3ce, 0x01 + (c << 8));    /* foreground color */
  1385.  
  1386.     outw(0x3ce, 0x30 + 0xc000);    /* pattern fill, color expansion */
  1387.     outw(0x3ce, 0x32 + 0x0d00);    /* operation: copy */
  1388.     outw(0x3ce, 0x31 + 0x0200);    /* start operation */
  1389.  
  1390.     cirrus_bltwait();
  1391.  
  1392.     outw(0x3ce, 0x01);    /* Disable Set/Reset. */
  1393. }
  1394.  
  1395. static int cirrus_hlinelistblt( int ymin, int n, int *xmin, int *xmax,
  1396. int pitch, int c ) {
  1397.     int srcaddr, i;
  1398.  
  1399.     if (pattern == -1)
  1400.         if (initializepattern())
  1401.             return -1;
  1402.  
  1403.     srcaddr = pattern;
  1404.  
  1405.     /* registers that won't change */
  1406.  
  1407.     outw(0x3ce, 0x2c + (srcaddr << 8));    /* bits 0-7 of src address */
  1408.     outw(0x3ce, 0x2d + (srcaddr & 0xff00));         /* bits 8-15 */
  1409.     outw(0x3ce, 0x2e + ((srcaddr & 0x1f0000) >> 8)); /* bits 16-20 */
  1410.  
  1411.     outw(0x3ce, 0x24 + (pitch << 8));    /* bits 0-7 of dest. pitch */
  1412.     outw(0x3ce, 0x25 + (pitch & 0xff00));    /* bits 8-11 */
  1413.  
  1414.     outw(0x3ce, 0x30 + 0xc000);    /* pattern fill, color expansion */
  1415.     outw(0x3ce, 0x01 + (c << 8));    /* foreground color */
  1416.     outw(0x3ce, 0x32 + 0x0d00);    /* operation: copy */
  1417.     outb(0x3ce, 0x31);
  1418.  
  1419.     for (i = 0; i < n; i++) {
  1420.         int w;
  1421.         int destaddr;
  1422.         w = xmax[i] - xmin[i] - 1;    /* discard rightmost pixel */
  1423.         if (w < 0)            /* (and -1 for chip) */
  1424.             continue;
  1425.  
  1426.         while (inb(0x3cf) & 1);        /* wait for blitter */
  1427.  
  1428.         outw(0x3ce, 0x20 + (w << 8));        /* bits 0-7 of width */
  1429.         outw(0x3ce, 0x21 + (w & 0x0700));    /* bits 8-10 */
  1430.  
  1431.         /* set height to 1 */
  1432.         outw(0x3ce, 0x22 + (0 << 8));        /* bits 0-7 of height */
  1433.         outw(0x3ce, 0x23 + (0 & 0x0300));    /* bits 8-9 */
  1434.  
  1435.         destaddr = (ymin + i) * pitch + xmin[i];
  1436.  
  1437.         outw(0x3ce, 0x28 + (destaddr << 8));
  1438.         outw(0x3ce, 0x29 + (destaddr & 0xff00));
  1439.         outw(0x3ce, 0x2a + ((destaddr & 0x1f0000) >> 8));
  1440.  
  1441.         outw(0x3ce, 0x31 + 0x0200);    /* start operation */
  1442.  
  1443.         CRITICAL = 1;
  1444.     }
  1445.     cirrus_bltwait();
  1446.     CRITICAL = 0;
  1447.  
  1448.     outw(0x3ce, 0x01);    /* Disable Set/Reset. */
  1449.     return 0;
  1450. }
  1451.  
  1452.  
  1453.  
  1454.  
  1455. /* Cirrus Logic acceleration functions implementation. */
  1456.  
  1457. /* BitBLT modes. */
  1458.  
  1459. #define FORWARDS        0x00
  1460. #define BACKWARDS        0x01
  1461. #define SYSTEMDEST        0x02
  1462. #define SYSTEMSRC        0x04
  1463. #define TRANSPARENCYCOMPARE    0x08
  1464. #define PIXELWIDTH16        0x10
  1465. #define PIXELWIDTH32        0x30    /* 543x only. */
  1466. #define PATTERNCOPY        0x40
  1467. #define COLOREXPAND        0x80
  1468.  
  1469. /* Macros for normal I/O BitBLT register access. */
  1470.  
  1471. #define SETSRCADDR(addr) \
  1472.     outw(0x3CE, (((addr) & 0x000000FF) << 8) | 0x2C); \
  1473.     outw(0x3CE, (((addr) & 0x0000FF00)) | 0x2D); \
  1474.     outw(0x3CE, (((addr) & 0x003F0000) >> 8) | 0x2E);
  1475.  
  1476. #define SETDESTADDR(addr) \
  1477.     outw(0x3CE, (((addr) & 0x000000FF) << 8) | 0x28); \
  1478.     outw(0x3CE, (((addr) & 0x0000FF00)) | 0x29); \
  1479.     outw(0x3CE, (((addr) & 0x003F0000) >> 8) | 0x2A);
  1480.  
  1481. /* Pitch: the 5426 goes up to 4095, the 5434 can do 8191. */
  1482.  
  1483. #define SETDESTPITCH(pitch) \
  1484.     outw(0x3CE, (((pitch) & 0x000000FF) << 8) | 0x24); \
  1485.     outw(0x3CE, (((pitch) & 0x00001F00)) | 0x25);
  1486.  
  1487. #define SETSRCPITCH(pitch) \
  1488.     outw(0x3CE, (((pitch) & 0x000000FF) << 8) | 0x26); \
  1489.     outw(0x3CE, (((pitch) & 0x00001F00)) | 0x27);
  1490.  
  1491. /* Width: the 5426 goes up to 2048, the 5434 can do 8192. */
  1492.  
  1493. #define SETWIDTH(width) \
  1494.     outw(0x3CE, ((((width) - 1) & 0x000000FF) << 8) | 0x20); \
  1495.     outw(0x3CE, ((((width) - 1) & 0x00001F00)) | 0x21);
  1496.  
  1497. /* Height: the 5426 goes up to 1024, the 5434 can do 2048. */
  1498. /* It appears many 5434's only go up to 1024. */
  1499.  
  1500. #define SETHEIGHT(height) \
  1501.     outw(0x3CE, ((((height) - 1) & 0x000000FF) << 8) | 0x22); \
  1502.     outw(0x3CE, (((height) - 1) & 0x00000700) | 0x23);
  1503.  
  1504. #define SETBLTMODE(m) \
  1505.     outw(0x3CE, ((m) << 8) | 0x30);
  1506.  
  1507. #define SETBLTWRITEMASK(m) \
  1508.     outw(0x3CE, ((m) << 8) | 0x2F);
  1509.  
  1510. #define SETTRANSPARENCYCOLOR(c) \
  1511.     outw(0x3CE, ((c) << 8) | 0x34);
  1512.  
  1513. #define SETTRANSPARENCYCOLOR16(c) \
  1514.     outw(0x3CE, ((c) << 8) | 0x34); \
  1515.     outw(0x3CE, (c & 0xFF00) | 0x35);
  1516.  
  1517. #define SETTRANSPARENCYCOLORMASK16(m) \
  1518.     outw(0x3CE, ((m) << 8) | 0x38); \
  1519.     outw(0x3CE, ((m) & 0xFF00) | 0x39);
  1520.  
  1521. #define SETROP(rop) \
  1522.     outw(0x3CE, ((rop) << 8) | 0x32);
  1523.  
  1524. #define SETFOREGROUNDCOLOR(c) \
  1525.     outw(0x3CE, 0x01 + ((c) << 8));
  1526.  
  1527. #define SETBACKGROUNDCOLOR(c) \
  1528.     outw(0x3CE, 0x00 + ((c) << 8));
  1529.  
  1530. #define SETFOREGROUNDCOLOR16(c) \
  1531.     outw(0x3CE, 0x01 + ((c) << 8)); \
  1532.     outw(0x3CE, 0x11 + ((c) & 0xFF00));
  1533.  
  1534. #define SETBACKGROUNDCOLOR16(c) \
  1535.     outw(0x3CE, 0x00 + ((c) << 8)); \
  1536.     outw(0x3CE, 0x10 + ((c) & 0xFF00)); \
  1537.  
  1538. #define SETFOREGROUNDCOLOR32(c) \
  1539.     outw(0x3CE, 0x01 + ((c) << 8)); \
  1540.     outw(0x3CE, 0x11 + ((c) & 0xFF00)); \
  1541.     outw(0x3CE, 0x13 + (((c) & 0xFf0000) >> 8)); \
  1542.     outw(0x3CE, 0x15 + (((unsigned int)(c) & 0xFF000000) >> 16));
  1543.  
  1544. #define SETBACKGROUNDCOLOR32(c) \
  1545.     outw(0x3CE, 0x00 + ((c) << 8)); \
  1546.     outw(0x3CE, 0x10 + ((c) & 0xFF00)); \
  1547.     outw(0x3CE, 0x12 + (((c) & 0xFF0000) >> 8)); \
  1548.     outw(0x3CE, 0x14 + (((unsigned int)(c) & 0xFF000000) >> 16));
  1549.  
  1550. #define STARTBLT() { \
  1551.     unsigned char tmp; \
  1552.     outb(0x3CE, 0x31); \
  1553.     tmp = inb(0x3CF); \
  1554.     outb(0x3CF, tmp | 0x02); \
  1555.     }
  1556.   
  1557. #define BLTBUSY(s) { \
  1558.     outb(0x3CE, 0x31); \
  1559.     s = inb(0x3CF) & 1; \
  1560.     }
  1561.  
  1562. #define WAITUNTILFINISHED() \
  1563.     for (;;) { \
  1564.         int busy; \
  1565.         BLTBUSY(busy); \
  1566.         if (!busy) \
  1567.             break; \
  1568.     }
  1569.  
  1570.  
  1571. /* Macros for memory-mapped I/O BitBLT register access. */
  1572.  
  1573. /* MMIO addresses (offset from 0xb8000). */
  1574.  
  1575. #define MMIOBACKGROUNDCOLOR    0x00
  1576. #define MMIOFOREGROUNDCOLOR    0x04
  1577. #define MMIOWIDTH        0x08
  1578. #define MMIOHEIGHT        0x0A
  1579. #define MMIODESTPITCH        0x0C
  1580. #define MMIOSRCPITCH        0x0E
  1581. #define MMIODESTADDR        0x10
  1582. #define MMIOSRCADDR        0x14
  1583. #define MMIOBLTWRITEMASK    0x17
  1584. #define MMIOBLTMODE        0x18
  1585. #define MMIOROP            0x1A
  1586. #define MMIOBLTSTATUS        0x40
  1587.  
  1588. #define MMIOSETDESTADDR(addr) \
  1589.   *(unsigned int *)(mmio_base + MMIODESTADDR) = addr;
  1590.  
  1591. #define MMIOSETSRCADDR(addr) \
  1592.   *(unsigned int *)(mmio_base + MMIOSRCADDR) = addr;
  1593.   
  1594. /* Pitch: the 5426 goes up to 4095, the 5434 can do 8191. */
  1595.  
  1596. #define MMIOSETDESTPITCH(pitch) \
  1597.   *(unsigned short *)(mmio_base + MMIODESTPITCH) = pitch;
  1598.  
  1599. #define MMIOSETSRCPITCH(pitch) \
  1600.   *(unsigned short *)(mmio_base + MMIOSRCPITCH) = pitch;
  1601.  
  1602. /* Width: the 5426 goes up to 2048, the 5434 can do 8192. */
  1603.  
  1604. #define MMIOSETWIDTH(width) \
  1605.   *(unsigned short *)(mmio_base + MMIOWIDTH) = (width) - 1;
  1606.  
  1607. /* Height: the 5426 goes up to 1024, the 5434 can do 2048. */
  1608.  
  1609. #define MMIOSETHEIGHT(height) \
  1610.   *(unsigned short *)(mmio_base + MMIOHEIGHT) = (height) - 1;
  1611.  
  1612. #define MMIOSETBLTMODE(m) \
  1613.   *(unsigned char *)(mmio_base + MMIOBLTMODE) = m;
  1614.  
  1615. #define MMIOSETBLTWRITEMASK(m) \
  1616.   *(unsigned char *)(mmio_base + MMIOBLTWRITEMASK) = m;
  1617.  
  1618. #define MMIOSETROP(rop) \
  1619.   *(unsigned char *)(mmio_base + MMIOROP) = rop;
  1620.  
  1621. #define MMIOSTARTBLT() \
  1622.   *(unsigned char *)(mmio_base + MMIOBLTSTATUS) |= 0x02;
  1623.  
  1624. #define MMIOBLTBUSY(s) \
  1625.   s = *(volatile unsigned char *)(mmio_base + MMIOBLTSTATUS) & 1;
  1626.  
  1627. #define MMIOSETBACKGROUNDCOLOR(c) \
  1628.   *(unsigned char *)(mmio_base + MMIOBACKGROUNDCOLOR) = c;
  1629.  
  1630. #define MMIOSETFOREGROUNDCOLOR(c) \
  1631.   *(unsigned char *)(mmio_base + MMIOFOREGROUNDCOLOR) = c;
  1632.  
  1633. #define MMIOSETBACKGROUNDCOLOR16(c) \
  1634.   *(unsigned short *)(mmio_base + MMIOBACKGROUNDCOLOR) = c;
  1635.  
  1636. #define MMIOSETFOREGROUNDCOLOR16(c) \
  1637.   *(unsigned short *)(mmio_base + MMIOFOREGROUNDCOLOR) = c;
  1638.  
  1639. #define MMIOSETBACKGROUNDCOLOR32(c) \
  1640.   *(unsigned int *)(mmio_base + MMIOBACKGROUNDCOLOR) = c;
  1641.  
  1642. #define MMIOSETFOREGROUNDCOLOR32(c) \
  1643.   *(unsigned int *)(mmio_base + MMIOFOREGROUNDCOLOR) = c;
  1644.  
  1645. #define MMIOWAITUNTILFINISHED() \
  1646.     for (;;) { \
  1647.         int busy; \
  1648.         MMIOBLTBUSY(busy); \
  1649.         if (!busy) \
  1650.             break; \
  1651.     }
  1652.  
  1653. static int cirrus_pattern_address;    /* Pattern with 1's (8 bytes) */
  1654. static int cirrus_bitblt_pixelwidth;
  1655. /* Foreground color is not preserved on 5420/2/4/6/8. */
  1656. static int cirrus_accel_foreground_color;
  1657.  
  1658. void cirrusaccel_init( AccelSpecs *accelspecs, int bpp, int width_in_pixels ) {
  1659.     /* [Setup accelerator screen pitch] */
  1660.     /* [Prepare any required off-screen space] */
  1661.     if (bpp == 8)
  1662.         cirrus_bitblt_pixelwidth = 0;
  1663.     if (bpp == 16)
  1664.         cirrus_bitblt_pixelwidth = PIXELWIDTH16;
  1665.     if (bpp == 32)
  1666.         cirrus_bitblt_pixelwidth = PIXELWIDTH32;
  1667.     SETSRCPITCH(accel_screenpitchinbytes);
  1668.     SETDESTPITCH(accel_screenpitchinbytes);
  1669.     SETROP(0x0D);
  1670.     cirrus_pattern_address = cirrus_memory * 1024 - 8;
  1671.     (*driverspecs->setpage)(cirrus_pattern_address / 65536);
  1672.     *(unsigned *)(__svgalib_graph_mem + (cirrus_pattern_address & 0xFFFF))
  1673.         = 0xFFFFFFFF;
  1674.     *(unsigned *)(__svgalib_graph_mem + (cirrus_pattern_address & 0xFFFF)
  1675.         + 4) = 0xFFFFFFFF;
  1676.     (*driverspecs->setpage)(0);
  1677.     if (cirrus_chiptype >= CLGD5429)
  1678.         /* Enable memory-mapped I/O. */
  1679.         outSR(0x17, inSR(0x17) | 0x04);
  1680. }
  1681.  
  1682.  
  1683. /*
  1684.  * Note: The foreground color register must always be reset to 0
  1685.  * on the 542x to avoid problems in normal framebuffer operation.
  1686.  * This is not the case on chips that support memory-mapped I/O.
  1687.  */
  1688.  
  1689. /*
  1690.  * These are two auxilliary functions to program the foreground
  1691.  * color depending on the current depth.
  1692.  */
  1693.  
  1694. static void set_foreground_color( int fg ) {
  1695.     if (accel_bytesperpixel == 1) {
  1696.         SETFOREGROUNDCOLOR(fg);
  1697.         return;
  1698.     }
  1699.     if (accel_bytesperpixel == 2) {
  1700.         SETFOREGROUNDCOLOR16(fg);
  1701.         return;
  1702.     }
  1703.     SETFOREGROUNDCOLOR32(fg);
  1704. }
  1705.  
  1706. static void mmio_set_foreground_color( int fg ) {
  1707.     if (accel_bytesperpixel == 1) {
  1708.         MMIOSETFOREGROUNDCOLOR(fg);
  1709.         return;
  1710.     }
  1711.     if (accel_bytesperpixel == 2) {
  1712.         MMIOSETFOREGROUNDCOLOR16(fg);
  1713.         return;
  1714.     }
  1715.     MMIOSETFOREGROUNDCOLOR32(fg);
  1716. }
  1717.  
  1718. #define FINISHBACKGROUNDBLITS() \
  1719.     if (accel_mode & BLITS_IN_BACKGROUND) \
  1720.         WAITUNTILFINISHED();
  1721.  
  1722. #define MMIOFINISHBACKGROUNDBLITS() \
  1723.     if (accel_mode & BLITS_IN_BACKGROUND) \
  1724.         MMIOWAITUNTILFINISHED();
  1725.  
  1726. void cirrusaccel_FillBox( int x, int y, int width, int height ) {
  1727.     int destaddr;
  1728.     destaddr = BLTBYTEADDRESS(x, y);
  1729.     width *= accel_bytesperpixel;
  1730.     FINISHBACKGROUNDBLITS();
  1731.     SETSRCADDR(cirrus_pattern_address);
  1732.     SETDESTADDR(destaddr);
  1733.     SETWIDTH(width);
  1734.     SETHEIGHT(height);
  1735.     set_foreground_color(cirrus_accel_foreground_color);
  1736.     SETBLTMODE(COLOREXPAND | PATTERNCOPY | cirrus_bitblt_pixelwidth);
  1737.     STARTBLT();
  1738.     WAITUNTILFINISHED();
  1739.     /* Can't easily run in background because foreground color has */
  1740.     /* to be restored. */
  1741.     SETFOREGROUNDCOLOR(0x00);
  1742. }
  1743.  
  1744. void cirrusaccel_mmio_FillBox( int x, int y, int width, int height ) {
  1745.     int destaddr;
  1746.     destaddr = BLTBYTEADDRESS(x, y);
  1747.     width *= accel_bytesperpixel;
  1748.     MMIOFINISHBACKGROUNDBLITS();
  1749.     MMIOSETSRCADDR(cirrus_pattern_address);
  1750.     MMIOSETDESTADDR(destaddr);
  1751.     MMIOSETWIDTH(width);
  1752.     MMIOSETHEIGHT(height);
  1753.     MMIOSETBLTMODE(COLOREXPAND | PATTERNCOPY | cirrus_bitblt_pixelwidth);
  1754.     MMIOSTARTBLT();
  1755.     if (!(accel_mode & BLITS_IN_BACKGROUND))
  1756.         MMIOWAITUNTILFINISHED();
  1757. }
  1758.  
  1759. void cirrusaccel_ScreenCopy( int x1, int y1, int x2, int y2, int width,
  1760. int height) {
  1761.     int srcaddr, destaddr, dir;
  1762.     width *= accel_bytesperpixel;
  1763.     srcaddr = BLTBYTEADDRESS(x1, y1);
  1764.     destaddr = BLTBYTEADDRESS(x2, y2);
  1765.     dir = FORWARDS;
  1766.     if ((y1 < y2 || (y1 == y2 && x1 < x2))
  1767.     && y1 + height > y2) {
  1768.         srcaddr += (height - 1) * accel_screenpitchinbytes + width - 1;
  1769.         destaddr += (height - 1) * accel_screenpitchinbytes + width - 1;
  1770.         dir = BACKWARDS;
  1771.     }
  1772.     FINISHBACKGROUNDBLITS();
  1773.     SETSRCADDR(srcaddr);
  1774.     SETDESTADDR(destaddr);
  1775.     SETWIDTH(width);
  1776.     SETHEIGHT(height);
  1777.     SETBLTMODE(dir);
  1778.     STARTBLT();
  1779.     if (!(accel_mode & BLITS_IN_BACKGROUND))
  1780.         WAITUNTILFINISHED();
  1781. }
  1782.  
  1783. void cirrusaccel_mmio_ScreenCopy( int x1, int y1, int x2, int y2, int width,
  1784. int height) {
  1785.     int srcaddr, destaddr, dir;
  1786.     width *= accel_bytesperpixel;
  1787.     srcaddr = BLTBYTEADDRESS(x1, y1);
  1788.     destaddr = BLTBYTEADDRESS(x2, y2);
  1789.     dir = FORWARDS;
  1790.     if ((y1 < y2 || (y1 == y2 && x1 < x2))
  1791.     && y1 + height > y2) {
  1792.         srcaddr += (height - 1) * accel_screenpitchinbytes + width - 1;
  1793.         destaddr += (height - 1) * accel_screenpitchinbytes + width - 1;
  1794.         dir = BACKWARDS;
  1795.     }
  1796.     MMIOFINISHBACKGROUNDBLITS();
  1797.     MMIOSETSRCADDR(srcaddr);
  1798.     MMIOSETDESTADDR(destaddr);
  1799.     MMIOSETWIDTH(width);
  1800.     MMIOSETHEIGHT(height);
  1801.     MMIOSETBLTMODE(dir);
  1802.     MMIOSTARTBLT();
  1803.     if (!(accel_mode & BLITS_IN_BACKGROUND))
  1804.         MMIOWAITUNTILFINISHED();
  1805. }
  1806.  
  1807. void cirrusaccel_SetFGColor( int fg ) {
  1808.     cirrus_accel_foreground_color = fg;
  1809. }
  1810.  
  1811. void cirrusaccel_mmio_SetFGColor( int fg ) {
  1812.     MMIOFINISHBACKGROUNDBLITS();
  1813.     mmio_set_foreground_color(fg);
  1814. }
  1815.  
  1816. static unsigned char cirrus_rop_map[] = {
  1817.     0x0D,    /* ROP_COPY */
  1818.     0x6D,    /* ROP_OR */
  1819.     0x05,    /* ROP_AND */
  1820.     0x59,    /* ROP_XOR */
  1821.     0x0B    /* ROP_INVERT */
  1822. };
  1823.  
  1824. void cirrusaccel_SetRasterOp( int rop ) {
  1825.     FINISHBACKGROUNDBLITS();
  1826.     SETROP(cirrus_rop_map[rop]);
  1827. }
  1828.  
  1829. void cirrusaccel_mmio_SetRasterOp( int rop ) {
  1830.     MMIOFINISHBACKGROUNDBLITS();
  1831.     MMIOSETROP(cirrus_rop_map[rop]);
  1832. }
  1833.  
  1834. void cirrusaccel_SetTransparency( int mode, int color ) {
  1835.     FINISHBACKGROUNDBLITS();
  1836.     if (mode == DISABLE_TRANSPARENCY_COLOR) {
  1837.         /* Disable. */
  1838.         SETTRANSPARENCYCOLORMASK16(0xFFFF);
  1839.         return;
  1840.     }
  1841.     if (mode == ENABLE_TRANSPARENCY_COLOR) {
  1842.         if (accel_bytesperpixel == 1)
  1843.             color += color << 8;
  1844.         SETTRANSPARENCYCOLORMASK16(0x0000);
  1845.         SETTRANSPARENCYCOLOR16(color);
  1846.         return;
  1847.     }
  1848.     if (mode == DISABLE_BITMAP_TRANSPARENCY) {
  1849.         accel_bitmaptransparency = 0;
  1850.         return;
  1851.     }
  1852.     /* mode == ENABLE_BITMAP_TRANSPARENCY */
  1853.     accel_bitmaptransparency = 1;
  1854. }
  1855.  
  1856. void cirrusaccel_Sync() {
  1857.     WAITUNTILFINISHED();
  1858. }
  1859.  
  1860. void cirrusaccel_mmio_Sync() {
  1861.     MMIOWAITUNTILFINISHED();
  1862. }
  1863.  
  1864.  
  1865. /*
  1866.  * Set up accelerator interface for pixels of size bpp and scanline width
  1867.  * of width_in_pixels.
  1868.  */
  1869.  
  1870. void init_acceleration_specs_for_mode( AccelSpecs *accelspecs, int bpp,
  1871. int width_in_pixels ) {
  1872.     accelspecs->operations = 0;
  1873.     accelspecs->ropOperations = 0;
  1874.     accelspecs->transparencyOperations = 0;
  1875.     if (cirrus_chiptype >= CLGD5426) {
  1876.         accelspecs->operations |= ACCELFLAG_SETMODE | ACCELFLAG_SYNC;
  1877.         if (bpp == 8 || bpp == 16) {
  1878.             /* BitBLT engine available. */
  1879.             accelspecs->operations |=
  1880.                 ACCELFLAG_FILLBOX | ACCELFLAG_SETFGCOLOR |
  1881.                 ACCELFLAG_SCREENCOPY |
  1882.                 ACCELFLAG_SETRASTEROP |
  1883.                 ACCELFLAG_SETTRANSPARENCY;
  1884.             accelspecs->ropOperations =
  1885.                 ACCELFLAG_FILLBOX | ACCELFLAG_SCREENCOPY;
  1886.             accelspecs->transparencyOperations =
  1887.                 ACCELFLAG_SCREENCOPY;
  1888.         }
  1889.         if (bpp == 24) {
  1890.             /* Depth-independent BitBLT functions. */
  1891.             accelspecs->operations |=
  1892.                 ACCELFLAG_SCREENCOPY;
  1893.             accelspecs->ropOperations =
  1894.                 ACCELFLAG_SCREENCOPY;
  1895.         }
  1896.     }
  1897.     if (cirrus_chiptype >= CLGD5429)
  1898.         if (bpp == 8 || bpp == 16) {
  1899.             /* Newer chips don't have true color-compare. */
  1900.             accelspecs->operations &= ~ACCELFLAG_SETTRANSPARENCY;
  1901.             accelspecs->transparencyOperations = 0;
  1902.         }
  1903.     if (cirrus_chiptype >= CLGD5434)
  1904.         if (bpp == 32) {
  1905.             /* BitBLT engine available for 32bpp. */
  1906.             accelspecs->operations |=
  1907.                 ACCELFLAG_FILLBOX | ACCELFLAG_SETFGCOLOR |
  1908.                 ACCELFLAG_SCREENCOPY |
  1909.                 ACCELFLAG_SETRASTEROP |
  1910.                 ACCELFLAG_SETTRANSPARENCY;
  1911.             accelspecs->ropOperations =
  1912.                 ACCELFLAG_FILLBOX | ACCELFLAG_SCREENCOPY;
  1913.         }
  1914. #if 0    /* Full potential. */
  1915.     /* 5420 */
  1916.     if (bpp == 8)
  1917.         /* Color-expand (extended write modes). */
  1918.         accelspecs->operations =
  1919.             ACCELFLAG_FILLBOX | ACCELFLAG_SETFGCOLOR | ACCELFLAG_DRAWHLINE |
  1920.             ACCELFLAG_DRAWHLINELIST;
  1921.     if (cirrus_chiptype >= CLGD5422)
  1922.         if (bpp == 16)
  1923.             /* Also for 16bpp. */
  1924.             accelspecs->operations =
  1925.                 ACCELFLAG_FILLBOX | ACCELFLAG_SETFGCOLOR |
  1926.                 ACCELFLAG_DRAWHLINE | ACCELFLAG_DRAWHLINELIST;
  1927.     if (cirrus_chiptype >= CLGD5426 && cirrus_memory >= 1024) {
  1928.         if (bpp == 8 || bpp == 16) {
  1929.             /* BitBLT engine available. */
  1930.             accelspecs->operations |=
  1931.                 ACCELFLAG_SCREENCOPY | ACCELFLAG_PUTIMAGE |
  1932.                 ACCELFLAG_SETBGCOLOR | ACCELFLAG_SETRASTEROP |
  1933.                 ACCELFLAG_SETTRANSPARENCY |
  1934.                 ACCELFLAG_PUTIMAGE | ACCELFLAG_PUTBITMAP
  1935.                 ACCELFLAG_SCREENCOPYBITMAP;
  1936.             accelspecs->ropOperations =
  1937.                 ACCELFLAG_FILLBOX | ACCELFLAG_SCREENCOPY |
  1938.                 ACCELFLAG_PUTIMAGE;
  1939.             accelspecs->transparencyOperations =
  1940.                 ACCELFLAG_SCREENCOPY | ACCELFLAG_PUTIMAGE |
  1941.                 ACCELFLAG_PUTBITMAP;
  1942.         }
  1943.         if (bpp == 24) {
  1944.             /* Depth-independent BitBLT functions. */
  1945.             accelspecs->operations |=
  1946.                 ACCELFLAG_SCREENCOPY | ACCELFLAG_PUTIMAGE;
  1947.             accelspecs->ropOperations =
  1948.                 ACCELFLAG_SCREENCOPY | ACCELFLAG_PUTIMAGE;
  1949.             /*
  1950.              * Possible additions: FILLBOX in bands, and
  1951.              * weird PutBitmap with color 0x000000 (trippling
  1952.              * bits with 8bpp operation).
  1953.              */
  1954.         }
  1955.     }
  1956.     if (cirrus_chiptype >= CLGD5429)
  1957.         if (bpp == 8 || bpp == 16) {
  1958.             /* Newer chips don't have true color-compare. */
  1959.             accelspecs->transparencyOperations = ACCELFLAG_BITMAP;
  1960.         }
  1961.     if (cirrus_chiptype >= CLGD5434)
  1962.         if (bpp == 32) {
  1963.             /* BitBLT engine available for 32bpp. */
  1964.             accelspecs->operations |=
  1965.                 ACCELFLAG_SCREENCOPY | ACCELFLAG_PUTIMAGE |
  1966.                 ACCELFLAG_SETBGCOLOR | ACCELFLAG_SETRASTEROP |
  1967.                 ACCELFLAG_SETTRANSPARENCY |
  1968.                 ACCELFLAG_PUTIMAGE | ACCELFLAG_PUTBITMAP
  1969.                 ACCELFLAG_SCREENCOPYBITMAP |
  1970.                 ACCELFLAG_DRAWHLINE | ACCELFLAG_DRAWHLINELIST;
  1971.             accelspecs->ropOperations =
  1972.                 ACCELFLAG_FILLBOX |
  1973.                 ACCELFLAG_SCREENCOPY | ACCELFLAG_PUTIMAGE;
  1974.             accelspecs->transparencyOperations =
  1975.                 ACCELFLAG_PUTBITMAP;
  1976.         }
  1977. #endif
  1978.     /* Set the function pointers; availability is handled by flags. */
  1979.     accelspecs->FillBox = cirrusaccel_FillBox;
  1980.     accelspecs->ScreenCopy = cirrusaccel_ScreenCopy;
  1981.     accelspecs->SetFGColor = cirrusaccel_SetFGColor;
  1982.     accelspecs->SetTransparency = cirrusaccel_SetTransparency;
  1983.     accelspecs->SetRasterOp = cirrusaccel_SetRasterOp;
  1984.     accelspecs->Sync = cirrusaccel_Sync;
  1985.     if (cirrus_chiptype >= CLGD5429) {
  1986.         accelspecs->FillBox = cirrusaccel_mmio_FillBox;
  1987.         accelspecs->ScreenCopy = cirrusaccel_mmio_ScreenCopy;
  1988.         accelspecs->SetFGColor = cirrusaccel_mmio_SetFGColor;
  1989.         /* No mmio-version of SetTransparency. */
  1990.         accelspecs->SetRasterOp = cirrusaccel_mmio_SetRasterOp;
  1991.         accelspecs->Sync = cirrusaccel_mmio_Sync;
  1992.     }
  1993. }
  1994.