home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / D / SVGALIB / SVGALIB1.TAR / svgalib / src / mach32.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-02-11  |  91.0 KB  |  3,573 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. /* ATI Mach32 driver (C) 1994 Michael Weller               */
  8. /* eowmob@exp-math.uni-essen.de mat42b@aixrs1.hrz.uni-essen.de       */
  9. /* eowmob@pollux.exp-math.uni-essen.de                   */
  10.  
  11. /*
  12.  *
  13.  * MICHAEL WELLER DISCLAIMS ALL WARRANTIES WITH REGARD
  14.  * TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
  15.  * FITNESS, IN NO EVENT SHALL MICHAEL WELLER BE LIABLE
  16.  * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  17.  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  18.  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  19.  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  20.  *
  21.  */
  22.  
  23. /* This tool contains one routine out of Xfree86, therefore I repeat    */
  24. /* its copyright here: (Actually it is longer than the copied code)     */
  25.  
  26. /*
  27.  * Copyright 1992 by Orest Zborowski <obz@Kodak.com>
  28.  * Copyright 1993 by David Wexelblat <dwex@goblin.org>
  29.  *
  30.  * Permission to use, copy, modify, distribute, and sell this software and its
  31.  * documentation for any purpose is hereby granted without fee, provided that
  32.  * the above copyright notice appear in all copies and that both that
  33.  * copyright notice and this permission notice appear in supporting
  34.  * documentation, and that the names of Orest Zborowski and David Wexelblat 
  35.  * not be used in advertising or publicity pertaining to distribution of 
  36.  * the software without specific, written prior permission.  Orest Zborowski
  37.  * and David Wexelblat make no representations about the suitability of this 
  38.  * software for any purpose.  It is provided "as is" without express or 
  39.  * implied warranty.
  40.  *
  41.  * OREST ZBOROWSKI AND DAVID WEXELBLAT DISCLAIMS ALL WARRANTIES WITH REGARD 
  42.  * TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND 
  43.  * FITNESS, IN NO EVENT SHALL OREST ZBOROWSKI OR DAVID WEXELBLAT BE LIABLE 
  44.  * FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 
  45.  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 
  46.  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
  47.  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  48.  *
  49.  * Copyright 1990,91 by Thomas Roell, Dinkelscherben, Germany.
  50.  * Copyright 1993 by Kevin E. Martin, Chapel Hill, North Carolina.
  51.  *
  52.  * Permission to use, copy, modify, distribute, and sell this software and its
  53.  * documentation for any purpose is hereby granted without fee, provided that
  54.  * the above copyright notice appear in all copies and that both that
  55.  * copyright notice and this permission notice appear in supporting
  56.  * documentation, and that the name of Thomas Roell not be used in
  57.  * advertising or publicity pertaining to distribution of the software without
  58.  * specific, written prior permission.  Thomas Roell makes no representations
  59.  * about the suitability of this software for any purpose.  It is provided
  60.  * "as is" without express or implied warranty.
  61.  *
  62.  * THOMAS ROELL, KEVIN E. MARTIN, AND RICKARD E. FAITH DISCLAIM ALL
  63.  * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED
  64.  * WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE AUTHORS
  65.  * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
  66.  * DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
  67.  * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
  68.  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  69.  *
  70.  * Author:  Thomas Roell, roell@informatik.tu-muenchen.de
  71.  *
  72.  * Rewritten for the 8514/A by Kevin E. Martin (martin@cs.unc.edu)
  73.  * Modified for the Mach-8 by Rickard E. Faith (faith@cs.unc.edu)
  74.  * Rewritten for the Mach32 by Kevin E. Martin (martin@cs.unc.edu)
  75.  *
  76.  */
  77.  
  78. /* Works only if Mach32 onboard VGA is enabled.               */
  79. /* Reads in eeprom.                            */
  80. /* There is a dirty hack in here to raise the linewidth for        */
  81. /* 800x600 to 832 to keep my mem happy.. (and even though it's a   */
  82. /* VRAM card... probably has to do something with mempages....     */
  83. /* I change it by tweaking the info array.. so watch out.          */
  84. /* The Number of additional pixels to append is set below, it has  */
  85. /* to be a multiple of 8. This seems only to be needed for 16/24bpp*/
  86. /* Ok,later I found that the number of pixels has to be a multiple */
  87. /* of 64 at least... somewhere in the  ATI docs, always choosing a */
  88. /* multiple of 128 was suggested....                               */
  89. /* So set the multiple to be used below..               */
  90.  
  91. #define PIXALIGN 64
  92.  
  93. #define DAC_SAFETY 0x15 /*reminder for people with DAC!=4,2,0*/
  94.             /*set bits for well known DACTYPES*/
  95.  
  96. #define MON_FUZ 0.5 /*How much do we allow modes to be above monitor freq.*/
  97.  
  98. #define SUPP_32BPP /*Accept 32BPP modes */
  99. /*#define USE_RGBa*/   /* ifdef(SUPP_32BPP) use RGBa format (R first in memory),
  100.               otherwise aBGR is used */
  101. /*Pure experimental and probably specific to my card (VRAM 68800-3)*/
  102. #define MAXCLK8  2000 /*This effectly switches this off.. seems not
  103.             to be needed with PIXTWEAK>32 */
  104. #define MAXCLK16 2000 /*This effectly switches this off.. seems not
  105.             to be needed with PIXTWEAK>32 */
  106. #define MAXCLK24 49
  107. #define MAXCLK32 39
  108.  
  109. /*And here are minimum Vfifo values.. just guessed values (valid settings are 0..15):*/
  110. #define VFIFO8    6
  111. #define VFIFO16    9
  112. #define VFIFO24    14
  113. #define VFIFO32    14
  114.  
  115. /*Wait count for busywait loops*/
  116. #define BUSYWAIT 10000000 /* Around 1-2 sec on my 486-50 this should be enough for
  117.                   any graphics command to complete, even on a fast machine.
  118.                   however after that slower code is called to ensure a minimum
  119.                   wait of another: */
  120. #define ADDIWAIT 5    /* seconds. */
  121.  
  122. /*#define FAST_MEMCPY*/    /* Use a very fast inline memcpy instead of the standard libc one */
  123.             /* Seems not to make a big difference for the Mach32 */
  124.             /* Even more seems to be MUCH slower than the libc memcpy, even */
  125.             /* though this uses a function call. Probably just rep movsb is */
  126.             /* fastest. So => do not use this feature. */
  127.  
  128. #define MODESWITCHDELAY    50000 /* used to wait for clocks to stabilize */
  129.  
  130. /*#define DEBUG*/
  131. /*#define DEBUG_KEY*/ /*Wait for keypress at some locations*/
  132. /*#define EXPERIMENTAL*/ /*Experimental flags*/
  133.  
  134. #include <stdio.h>
  135. #include <stdlib.h>
  136. #include <stdarg.h>
  137. #include <unistd.h>
  138. #include <errno.h>
  139. #include <string.h>
  140. #include <ctype.h>
  141. #include <time.h>
  142. #include <sys/types.h>
  143. #include <sys/mman.h>
  144.  
  145. #include "mach32.h"
  146. #include "vga.h"
  147. #include "libvga.h"
  148. #include "driver.h"
  149. #include "config.h"
  150.  
  151. /*List preallocate(for internal info table mixup commands):*/
  152. #define PREALLOC 16
  153.  
  154. /*Internal mixup commands:*/
  155. #define CMD_MSK 0xf000
  156. #define CMD_ADD 0x0000
  157. #define CMD_DEL 0x1000
  158. #define CMD_MOD 0x2000
  159. #define CMD_CPY 0x3000
  160. #define CMD_MOV 0x4000
  161.  
  162. #define ATIPORT        0x1ce
  163. #define ATIOFF        0x80
  164. #define ATISEL(reg)    (ATIOFF+reg)
  165.  
  166. /* Ports we use: */
  167. #define CMD        0x9AE8
  168. #define ALU_FG_FN    0xBAEE
  169. #define ALU_BG_FN    0xB6EE
  170. #define EXT_SCISSOR_B    0xE6EE
  171. #define EXT_SCISSOR_L    0xDAEE
  172. #define EXT_SCISSOR_R    0xE6EE
  173. #define EXT_SCISSOR_T    0xDEEE
  174. #define DP_CONFIG    0xCEEE
  175. #define FRGD_MIX    0xBAE8
  176. #define BKGD_MIX    0xBAE8
  177. #define FRGD_COLOR    0xA6E8
  178. #define CUR_X        0x86E8
  179. #define CUR_Y        0x82E8
  180. #define MAJ_AXIS_PCNT    0x96E8
  181. #define DEST_CMP_FN    0xEEEE
  182. #define MULTI_FUNC_CNTL    0xBEE8
  183. #define EXT_FIFO_STATUS    0x9AEE
  184. #define SUBSYS_CNTL    0x42E8
  185. #define SUBSYS_STAT    0x42E8
  186. #define VGA_DAC_MASK    0x3C6
  187. #define SCRATCH_PAD_0    0x52EE
  188. #define DESTX_DIASTP    0x8EE8
  189. #define DESTY_AXSTP    0x8AE8
  190. #define R_SRC_X        0xDAEE
  191. #define SRC_X        0x8EE8
  192. #define SRC_Y        0x8AE8
  193. #define SRC_X_START    0xB2EE
  194. #define SRC_X_END    0xBEEE
  195. #define SRC_Y_DIR    0xC2EE
  196. #define    SCAN_TO_X    0xCAEE
  197. #define DEST_X_START    0xA6EE
  198. #define DEST_X_END    0xAAEE
  199. #define DEST_Y_END    0xAEEE
  200. #define GE_STAT        0x9AE8
  201. #define CONF_STAT1    0x12EE
  202. #define CONF_STAT2    0x16EE
  203. #define MISC_OPTIONS    0x36EE
  204. #define MEM_CFG        0x5EEE
  205. #define MEM_BNDRY    0x42EE
  206. #define LOCAL_CNTL    0x32EE
  207. #define CHIP_ID        0xFAEE
  208. #define EXT_GE_CONF    0x7AEE
  209. #define R_EXT_GE_CONF    0x8EEE
  210. #define DISP_CNTL    0x22E8
  211. #define CLOCK_SEL    0x4AEE
  212. #define GE_PITCH    0x76EE
  213. #define GE_OFFSET_HI    0x72EE
  214. #define GE_OFFSET_LO    0x6EEE
  215. #define CRT_PITCH    0x26EE
  216. #define CRT_OFFSET_HI    0x2EEE
  217. #define CRT_OFFSET_LO    0x2AEE
  218. #define H_DISP        0x06E8
  219. #define H_TOTAL        0x02E8
  220. #define H_SYNC_WID    0x0EE8
  221. #define H_SYNC_STRT    0x0AE8
  222. #define V_DISP        0x16E8
  223. #define V_SYNC_STRT    0x1AE8
  224. #define V_SYNC_WID    0x1EE8
  225. #define V_TOTAL        0x12E8
  226. #define    R_H_TOTAL       0xB2EE
  227. #define    R_H_SYNC_STRT    0xB6EE
  228. #define    R_H_SYNC_WID    0xBAEE
  229. #define    R_V_TOTAL    0xC2EE
  230. #define    R_V_DISP    0xC6EE
  231. #define    R_V_SYNC_STRT    0xCAEE
  232. #define    R_V_SYNC_WID    0xD2EE
  233. #define    SHADOW_SET    0x5AEE
  234. #define SHADOW_CTL    0x46EE
  235. #define MISC_CTL    0x7EEE
  236. #define R_MISC_CTL    0x92EE
  237. #define DISP_STATUS    0x2E8
  238.  
  239. #define DAC_W_INDEX    0x02EC
  240. #define DAC_DATA    0x02ED
  241. #define DAC_MASK    0x02EA
  242. #define DAC_R_INDEX    0x02EB
  243.  
  244. #define DAC0        0x02EC
  245. #define DAC1        0x02ED
  246. #define DAC2        0x02EA
  247. #define DAC3        0x02EB
  248.  
  249. /* Bit masks: */
  250. #define GE_BUSY        0x0200
  251. #define ONLY_8514    1
  252. #define LOCAL_BUS_CONF2    (1<<6)
  253. #define BUS_TYPE    0x000E
  254. #define PCI        0x000E
  255. #define ISA        0x0000
  256. #define Z4GBYTE        (1<<13)
  257.  
  258. /* ATI-EXT regs to save (ensure lock regs are set latest, that is they are listed first here!): */
  259. static const unsigned char mach32_eregs[]={
  260.     /* Lock regs: */
  261.     0x38,0x34,0x2e,0x2b,
  262.     /* All other extended regs. */
  263.     0x00,0x01,0x02,0x03,0x04,0x05,0x06,
  264.     0x20,0x23,0x24,0x25,0x26,0x27,0x2c,
  265.     0x2d,0x30,0x31,0x32,0x33,0x35,0x36,
  266.     0x37,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,
  267.     0x3f };
  268.  
  269. /* Extended ATI VGA regs that have to be reset for plain vga-modes */
  270. /* First num is ATI reg, 2nd has bits set where to clear bits in the*/
  271. /* ATI reg. Note: the most important clocksel regs 0x38 & 0x39 are */
  272. /* handled manually */
  273. static const unsigned char mach32_ati_ext[]={
  274.     0x05,    0x80,    /* VGA std blink rate */
  275.     0x23,    0x18,    /* clear ext CRTC bits */
  276.     0x26,    0xc1,    /* no skew of disp enab, dashedunderl */
  277.     0x27,    0xf1,
  278.     0x2c,    0x41,
  279.     0x2d,    0xff,    /* several ext bits*/
  280.     0x2e,    0xef,    /* ext page pointers */
  281.     0x30,    0x65,
  282.     0x31,    0x7b,
  283.     0x32,    0xff,
  284.     0x33,    0xc0,
  285.     0x34,    0x03,
  286.     0x35,    0xf7,
  287.     0x36,    0xf7,
  288.     0x3d,    0x0d,
  289.     0x3e,    0xdf};
  290.     
  291.     
  292. /* Mach32 regs to save.. read, write address alternating: */
  293. static const unsigned short mach32_acc_regs[]={
  294.     0xB2EE, 0x06E8,        /* H_DISP(ALT H_TOTAL) */
  295.     0xC2EE,    0x12E8,        /* V_TOTAL */
  296.     0xC6EE, 0x16E8,        /* V_DISP */
  297.     0xCAEE, 0x1AE8,        /* V_SYNC_STRT */
  298.     0xD2EE, 0x1EE8,        /* V_SYNC_WID */
  299.     0x4AEE, 0x4AEE,        /* CLOCK_SEL */
  300.     0x96EE, 0x96EE,        /* BRES_COUNT */
  301.     0x86E8, 0x86E8,        /* CUR_X */
  302.     0x82E8, 0x82E8,        /* CUR_Y */
  303.     0x22EE,    0x22EE,        /* DAC_CONT(PCI) */
  304.     0xF2EE,    0xF2EE,        /* DEST_COLOR_CMP_MASK */
  305.     0x92E8,    0x92E8,        /* ERR_TERM */
  306.     0xA2EE,    0xA2EE,        /* LINEDRAW_OPT */
  307.     0x32EE,    0x32EE,        /* LOCAL_CNTL */
  308.     0x6AEE,    0x6AEE,        /* MAX_WAITSTATES / MISC_CONT(PCI) */
  309.     0x36EE,    0x36EE,        /* MISC_OPTIONS */
  310.     0x82EE,    0x82EE,        /* PATT_DATA_INDEX */
  311.     0x8EEE,    0x7AEE,        /* EXT_GE_CONFIG */
  312.     0xB6EE, 0x0AE8,        /* H_SYNC_STRT */
  313.     0xBAEE, 0x0EE8,        /* H_SYNC_WID */
  314.     0x92EE, 0x7EEE,        /* MISC_CNTL */
  315.     0xDAEE, 0x8EE8,        /* SRC_X */
  316.     0xDEEE, 0x8AE8,        /* SRC_Y */
  317.     0x52EE, 0x52EE,        /* SCRATCH0 */
  318.     0x56EE, 0x56EE,        /* SCRATCH1 */
  319.     0x42EE, 0x42EE,        /* MEM_BNDRY */
  320.     0x5EEE, 0x5EEE,        /* MEM_CFG */
  321.     };
  322.  
  323. #define PAGE_UNKNOWN 0
  324. #define PAGE_DIFF    1
  325. #define PAGE_BOTH    2
  326.  
  327. #define DAC_MODE8    0
  328. #define DAC_MODEMUX  1
  329. #define DAC_MODE555  2
  330. #define DAC_MODE565  3
  331. #define DAC_MODERGB  4
  332. #define DAC_MODE32B  5
  333. #define DAC_SEMICLK  0x80
  334.  
  335. #define EMU_POSS     1
  336. #define EMU_OVER     2
  337.  
  338. #define EEPROM_USE_CHKSUM    1
  339. #define EEPROM_USE_MEMCFG    2
  340. #define EEPROM_USE_TIMING    4
  341. #define EEPROM_UPDATE        8
  342.  
  343. /*DAC_MODETABLES:   */
  344. static const unsigned char mach32_dac1[4]={0x00,0x00,0xa2,0xc2};
  345.  
  346. static const unsigned char mach32_dac4[5]={0x00,0x00,0xa8,0xe8,0xf8};
  347.  
  348. static const unsigned char mach32_dac5[6]={0x00,0x00,0x20,0x21,0x40,
  349. #ifdef USE_RGBa
  350.                       0x61
  351. #else
  352.                       0x60
  353. #endif
  354.                       };
  355.  
  356. typedef struct    {
  357.         unsigned char vfifo16,vfifo24;
  358.         unsigned char h_disp, h_total, h_sync_wid, h_sync_strt;
  359.         unsigned short v_total, v_disp, v_sync_strt;
  360.         unsigned char disp_cntl, v_sync_wid;
  361.         unsigned short clock_sel, flags, mask, offset;
  362.         } mode_entry;
  363.  
  364. typedef enum { R_UNKNOWN , R_STANDARD , R_EXTENDED } accelstate;
  365.  
  366. /*sizeof mode_entry in shorts:*/
  367. #define SOMOD_SH ((sizeof(mode_entry)+sizeof(short)-1)/sizeof(short))
  368.  
  369. /*I put the appropriate VFIFO values from my selfdefined modes in... raise them if you get
  370.   strange screen flickering.. (but they have to be <=0xf !!!!)*/
  371. static const mode_entry predef_modes[]={
  372.         {0x9, 0xe, 0x4f, 0x63, 0x2c, 0x52, 0x418, 0x3bf, 0x3d6, 0x23, 0x22, 0x50, 0, 0x0000, 0},
  373.         {0x9, 0xe, 0x4f, 0x69, 0x25, 0x52, 0x40b, 0x3bf, 0x3d0, 0x23, 0x23, 0x24, 0, 0x0001, 7},
  374.         {0x9, 0xe, 0x63, 0x84, 0x10, 0x6e, 0x580, 0x4ab, 0x4c2, 0x33, 0x2c, 0x7c, 0, 0x003f, 8},
  375.         {0x9, 0xe, 0x63, 0x84, 0x10, 0x6d, 0x580, 0x4ab, 0x4c2, 0x33, 0x0c, 0x0c, 0, 0x003d, 8},
  376.         {0x9, 0xe, 0x63, 0x7f, 0x09, 0x66, 0x4e0, 0x4ab, 0x4b0, 0x23, 0x02, 0x0c, 0, 0x003c, 8},
  377.         {0x9, 0xe, 0x63, 0x83, 0x10, 0x68, 0x4e3, 0x4ab, 0x4b3, 0x23, 0x04, 0x30, 0, 0x0038, 8},
  378.         {0x9, 0xe, 0x63, 0x7d, 0x12, 0x64, 0x4f3, 0x4ab, 0x4c0, 0x23, 0x2c, 0x1c, 0, 0x0030, 8},
  379.         {0x9, 0xe, 0x63, 0x82, 0x0f, 0x6a, 0x531, 0x4ab, 0x4f8, 0x23, 0x06, 0x10, 0, 0x0020, 8},
  380.         {0xd, 0xe, 0x7f, 0x9d, 0x16, 0x81, 0x668, 0x5ff, 0x600, 0x33, 0x08, 0x1c, 0, 0x0001, 9},
  381.         {0xd, 0xe, 0x7f, 0xa7, 0x31, 0x82, 0x649, 0x5ff, 0x602, 0x23, 0x26, 0x3c, 0, 0x0003, 9},
  382.         {0xd, 0xe, 0x7f, 0xad, 0x16, 0x85, 0x65b, 0x5ff, 0x60b, 0x23, 0x04, 0x38, 0, 0x0013, 9},
  383.         {0xd, 0xe, 0x7f, 0xa5, 0x31, 0x83, 0x649, 0x5ff, 0x602, 0x23, 0x26, 0x38, 0, 0x0017, 9},
  384.         {0xd, 0xe, 0x7f, 0xa0, 0x31, 0x82, 0x649, 0x5ff, 0x602, 0x23, 0x26, 0x38, 0, 0x001f, 9},
  385.         {0xe, 0xe, 0x9f, 0xc7, 0x0a, 0xa9, 0x8f8, 0x7ff, 0x861, 0x33, 0x0a, 0x2c, 0, 0x0001, 10},
  386.         {0xe, 0xe, 0x9f, 0xc7, 0x0a, 0xa9, 0x838, 0x7ff, 0x811, 0x33, 0x0a, 0x2c, 0, 0x0003, 10},
  387.         };
  388.  
  389. #define NUM_MODES (sizeof(predef_modes)/sizeof(mode_entry))
  390.  
  391. static const mode_entry * *mach32_modes=NULL;
  392.  
  393. static int mach32_clocks[32]={ /* init to zero for safety */
  394.     0, 0, 0, 0, 0, 0, 0, 0,
  395.     0, 0, 0, 0, 0, 0, 0, 0,
  396.     0, 0, 0, 0, 0, 0, 0, 0,
  397.     0, 0, 0, 0, 0, 0, 0, 0};
  398.     
  399. static signed char mach32_clock_by2[32],mach32_clock_by3[32];
  400.  
  401. /*Bitmask is 1 256-col, 2 15-16 bpp, 4 24 bpp, 8 32bpp*/
  402. static unsigned char mach32_mmask[2][8]={
  403.     {/* General supported modes..*/ 3,3,0xf,1,0x7,0xf,1,1},
  404.     {/* Modes above 80Mhz..      */ 0,0,  1,0,  0,0xf,0,0}};
  405.  
  406. /* Modes that ATI mentions for it's DACS.. this is for safety and the internal
  407.    predefined modes.. I think the above restrictions should be enough.. However
  408.    I don't want to risk the life of your DAC so.. */
  409. static unsigned char dacmo640[] ={0x3,0x3,0xf,0x1,0x7,0xf,0x1,0x1};
  410. static unsigned char dacmo800[] ={0x3,0x3,0xf,0x1,0x3,0xf,0x1,0x1};
  411. static unsigned char dacmo1024[] ={0x3,0x1,0x3,0x1,0x1,0xf,0x1,0x1};
  412. static unsigned char dacmo1280[] ={0x0,0x0,0x1,0x0,0x0,0xf,0x0,0x0};
  413.  
  414. static float mach32_monitor[6]={31.5+MON_FUZ, 35.1+MON_FUZ, 35.5+MON_FUZ,
  415.                 37.9+MON_FUZ, 48.3+MON_FUZ, 56.0+MON_FUZ};
  416.  
  417. /* several globals.. mostly to record current state of the driver */
  418. static char vfifo8=VFIFO8,vfifo16=VFIFO16,vfifo24=VFIFO24,vfifo32=VFIFO32,mach32_apsiz=0;
  419. static char *eeprom_fname=NULL,offset_follows=1,pitch_follows=1;
  420. static char emuimage=EMU_POSS|EMU_OVER;    /* Never set EMU_OVER w/o EMU_POSS !!! */
  421. static char eeprom_option=EEPROM_USE_CHKSUM|EEPROM_USE_MEMCFG|EEPROM_USE_TIMING;
  422.  
  423. static unsigned short *mach32_eeprom, mach32_disp_shadow=0,mach32_strictness=0,*mach32_modemixup;
  424. static unsigned short mach32_apadd=1,mach32_memcfg,mach32_ge_pitch,mach32_ge_off_h;
  425. static unsigned short mach32_ge_off_l;
  426.  
  427. static int mach32_memory,mach32_dac,mach32_pagemode=PAGE_UNKNOWN,mach32_dacmode=DAC_MODE8;
  428. static int mach32_chiptype,mixup_alloc=0,mixup_ptr=0,clocks_set=0,ext_settings=0;
  429. static int mach32_maxclk8=MAXCLK8,mach32_maxclk16=MAXCLK16,mach32_maxclk24=MAXCLK24;
  430. static int mach32_maxclk32=MAXCLK32,latchopt= ~0,bladj= -1;
  431. static int pos_ext_settings=VGA_CLUT8;
  432. static int acc_supp=HAVE_BLITWAIT|HAVE_FILLBLIT|HAVE_IMAGEBLIT|HAVE_BITBLIT|HAVE_HLINELISTBLIT;
  433.  
  434. static accelstate mach32_accelstate=R_UNKNOWN;
  435.  
  436. #ifdef DEBUG
  437. static char verbose=1;
  438. #else
  439. static char verbose=0;
  440. #endif
  441. #ifdef EXPERIMENTAL
  442. static unsigned mach32_experimental=0;
  443. #endif
  444.  
  445.  
  446. static volatile char *mach32_aperture=NULL;
  447. static volatile int dummy;
  448.  
  449. static signed char mach32_search_clk(int clk);
  450. static void mach32_setstate(accelstate which);
  451. static void mach32_blankadj(int adj);
  452. static void mach32_modfill(const mode_entry * mode, int modemask, int forcein);
  453. static int mach32_test(void);
  454. static int mach32_init(int force, int chiptype, int memory);
  455. static void mach32_i_bltwait(void);
  456. static int mach32_bltwait(void);
  457. static void mach32_wait(void);
  458. static void mach32_experm(void);
  459. static int mach32_eeclock(register int ati33);
  460. static void mach32_eekeyout(register int ati33, register int offset, register int mask);
  461. static int mach32_eeget(int offset);
  462. static int mach32_saveregs(unsigned char regs[]);
  463. static int mach32_setregs(unsigned char regs[]);
  464. static int mach32_unlock(void);
  465. static int mach32_lock(void);
  466. static int mach32_sav_dac(int offset,unsigned char regs[]);
  467. static int mach32_set_dac(int dac_mode, int clock_intended,int xres);
  468. static void mach32_setpage(int page);
  469. static void mach32_setrdpage(int page);
  470. static void mach32_setwrpage(int page);
  471. static void mach32_setappage(int page);
  472. static void mach32_setdisplaystart(int address);
  473. static void mach32_setlogicalwidth(int width);
  474. static int mach32_modeavailable(int mode);
  475. static int mach32_getmodeinfo(int mode,vga_modeinfo *modeinfo);
  476. static int mach32_setmode(int mode, int previous);
  477. static int mach32_bitblt(int srcaddr, int destaddr, int w, int h, int pitch);
  478. static int mach32_fillblt(int destaddr, int w, int h, int pitch, int c);
  479. static void mach32_imageblt(void *srcaddr,int destaddr, int w, int h, int pitch);
  480. static void mach32_memimageblt(void *srcaddr,int destaddr, int w, int h, int pitch);
  481. static int mach32_hlinelistblt(int ymin, int n, int *xmin, int *xmax, int pitch, int c);
  482. static void mach32_readconfig(void);
  483. static void mach32_final_modefixup(void);
  484. static int mach32_ext_set(unsigned what, va_list params);
  485. static int mach32_accel(unsigned operation, va_list params);
  486. static void mach32_ge_reset(void);
  487. static void slow_queue(unsigned short mask);
  488.  
  489. DriverSpecs mach32_driverspecs = {
  490.     mach32_saveregs,/* saveregs */
  491.     mach32_setregs,/* setregs */
  492.     mach32_unlock,    /* unlock */
  493.     mach32_lock,    /* lock */
  494.     mach32_test,
  495.     mach32_init,
  496.     mach32_setpage,    /* setpage */
  497.     mach32_setrdpage,    /* setrdpage */
  498.     mach32_setwrpage,    /* setwrpage */
  499.     mach32_setmode,    /* setmode */
  500.     mach32_modeavailable, /* modeavailable */
  501.     mach32_setdisplaystart, /* setdisplaystart */
  502.     mach32_setlogicalwidth, /* setlogicalwidth */
  503.     mach32_getmodeinfo, /* getmodeinfo */
  504.     mach32_bitblt, /* bitblt */
  505.     mach32_imageblt, /* imageblt */
  506.     mach32_fillblt, /* fillblt */
  507.     mach32_hlinelistblt, /* hlinelistblt */
  508.     mach32_bltwait, /* bltwait */
  509.     mach32_ext_set,
  510.     mach32_accel,
  511.     0,    /* linear -- mach32 driver handles it differently */
  512.     NULL    /* accelspecs */
  513. };
  514.  
  515. #ifdef FAST_MEMCPY
  516. /* This memcpy is immediately derived from memset as given in speedtest.c in this
  517.    same svgalib package written by Harm Hanemaayer */
  518.  
  519. static inline void *fast_memcpy( void *dest, void *source, size_t count ) {
  520. __asm__(
  521.     "cld\n\t"
  522.     "cmpl $12,%%edx\n\t"
  523.     "jl 1f\n\t"            /* if (count >= 12) */
  524.  
  525.     "movl %%edx,%%ecx\n\t"
  526.     "negl %%ecx\n\t"
  527.     "andl $3,%%ecx\n\t"        /* (-s % 4) */
  528.     "subl %%ecx,%%edx\n\t"        /* count -= (-s % 4) */
  529.     "rep ; movsb\n\t"        /* align to longword boundary */
  530.  
  531.     "movl %%edx,%%ecx\n\t"
  532.     "shrl $2,%%ecx\n\t"
  533.     
  534.     /* Doing any loop unrolling here proved to SLOW!!! down
  535.            the copy on my system, at least it didn't show any speedup. */
  536.  
  537.     "rep ; movsl\n\t"        /* copy remaining longwords */
  538.  
  539.     "andl $3,%%edx\n"        /* copy last few bytes */
  540.     "1:\tmovl %%edx,%%ecx\n\t"    /* <= 12 entry point */
  541.     "rep ; movsb\n\t" :
  542.     /* no outputs */ :
  543.     /* inputs */
  544.         /* SI= source address */    "S" (source),
  545.         /* DI= destination address */    "D" (dest),
  546.         /* CX= words to transfer */    "d" (count) :
  547.     /* eax, edx, esi, edi, ecx destructed: */ "%eax","%edx","%esi","%edi","%ecx" );
  548. return dest;
  549. }
  550. #else
  551. #define fast_memcpy memcpy
  552. #endif
  553.  
  554. static inline int max(int a,int b)
  555. {
  556. return (a>b)?a:b;
  557. }
  558.  
  559. static inline void checkqueue(int n)    /* This checks for at least n free queue positions */
  560. {
  561. /*Prepare mask:*/
  562. unsigned short mask= (unsigned short)(0xffff0000>>n);
  563. int i=BUSYWAIT;
  564.  
  565. while(i--)
  566.     if(!(inw(EXT_FIFO_STATUS)&mask))
  567.         return;
  568.  
  569. slow_queue(mask);
  570. }
  571.  
  572. static void slow_queue(unsigned short mask)
  573. {
  574. clock_t clk_time;
  575.  
  576. clk_time=clock();
  577.  
  578. do    {
  579.     if(!(inw(EXT_FIFO_STATUS)&mask))
  580.         return;
  581.     }
  582. while( (clock()-clk_time) < (CLOCKS_PER_SEC*ADDIWAIT) );
  583.  
  584. mach32_ge_reset();    /* Give up */
  585. }
  586.  
  587. static void mach32_ge_reset(void)    /* This is intended as a safety bailout if we locked
  588.                        up the card. */
  589. {
  590. int queue_stat,ioerr,ge_stat;
  591. int i=1000000;
  592. volatile int dummy;
  593.  
  594. /* Provide diagnostics: */
  595. ioerr=inw(SUBSYS_STAT);
  596. queue_stat=inw(EXT_FIFO_STATUS);
  597. ge_stat=inw(GE_STAT);
  598.  
  599.  
  600. outw(SUBSYS_CNTL,0x800f);    /*Reset GE, disable all IRQ, reset all IRQ state bits*/
  601. while(i--)
  602.     dummy++;
  603. outw(SUBSYS_CNTL,0x400f);    /*Continue normal operation*/
  604. /* Better reconfigure all used registers */
  605. mach32_accelstate=R_UNKNOWN;
  606. CRITICAL=0;    /* Obviously we are idle */
  607. puts("\asvgalib: mach32: Warning! GE_Engine timed out, draw command\n"
  608.        "was probably corrupted! If you have a very fast machine (10*Pentium)\n"
  609.        "raise BUSYWAIT and ADDIWAIT in mach32.c, may also be a driver/card bug,\n"
  610.        "so report detailed info to me (Michael Weller).\nBUT:\n"
  611.        "This reaction is normal when svgalib is killed in a very critical operation\n"
  612.        "by a fatal signal like INT (pressing ^C). In this situation this reset just\n"
  613.        "guarantees that you can continue working on the console, so in this case\n"
  614.        "PLEASE don't bloat my mailbox with bug reports. Thx, Michael.");
  615. printf("POST-Mortem:\n\tSubsys stat: %04x - %sIOerror (is usually a queue overrun)\n"
  616.        "\tGE stat    : %04x - engine %s, %sdata ready for host.\n\tQueue stat : %04x\n",
  617.     ioerr,(ioerr&4)?"":"no ",ge_stat,
  618.     (ge_stat&GE_BUSY)?"busy":"idle",(ge_stat&0x100)?"":"no ",queue_stat);
  619. }
  620.  
  621. static void mach32_setstate(accelstate which)    /* Set GE registers to values assumed elsewhere*/
  622. {
  623. mach32_accelstate=which;
  624.  
  625. if(which==R_STANDARD)
  626.     {
  627.     checkqueue(6);
  628.     outw(BKGD_MIX,0x0027);        /* Not used .. however ensure PIX_TRANS is not used */
  629.     /*Effectively switch off hardware clipping: */
  630.     outw(MULTI_FUNC_CNTL,0x1000|(0xfff& -1));    /*TOP*/
  631.     outw(MULTI_FUNC_CNTL,0x2000|(0xfff& -1));    /*LEFT*/
  632.     outw(MULTI_FUNC_CNTL,0x3000|1535);        /*BOTTOM*/
  633.     outw(MULTI_FUNC_CNTL,0x4000|1535);        /*RIGHT*/
  634.     /*Same for ATI EXT commands:*/
  635.     checkqueue(6);
  636.     outw(EXT_SCISSOR_T,0xfff& -512);    /*TOP*/
  637.     outw(EXT_SCISSOR_L,0xfff& -512);    /*LEFT*/
  638.     outw(EXT_SCISSOR_B,1535);        /*BOTTOM*/
  639.     outw(EXT_SCISSOR_R,1535);        /*RIGHT*/
  640.     outw(MULTI_FUNC_CNTL,0xa000);
  641.     outw(ALU_FG_FN,7);
  642.     checkqueue(2);
  643.     outw(DEST_CMP_FN,0);            /* Just draw */
  644.     outw(DP_CONFIG,0x3291);
  645.     }
  646. else    {
  647.     /* The following 3 may not always be needed */
  648.     checkqueue(3);
  649.     outw(GE_OFFSET_LO,mach32_ge_off_l);
  650.     outw(GE_OFFSET_HI,mach32_ge_off_h);
  651.     outw(GE_PITCH,mach32_ge_pitch);
  652.     }
  653. }
  654.  
  655. static void mach32_setdisplaystart(int address)
  656. {
  657. unsigned short tmp;
  658.  
  659. #ifdef DEBUG
  660. printf("mach32_setdisplaystart(%x)\n",address);
  661. #endif
  662. tmp=address>>2;
  663. outw(CRT_OFFSET_LO,tmp);
  664. if(offset_follows)
  665.     {
  666.     mach32_ge_off_l=tmp;
  667.     if(mach32_accelstate==R_EXTENDED)
  668.         {
  669.         checkqueue(2);
  670.         outw(GE_OFFSET_LO,tmp);
  671.         }
  672.     }
  673. tmp=0xff&(address>>18);
  674. outw(CRT_OFFSET_HI,tmp);
  675. if(offset_follows)
  676.     {
  677.     mach32_ge_off_h=tmp;
  678.     if(mach32_accelstate==R_EXTENDED)
  679.         {
  680.         checkqueue(1);
  681.         outw(GE_OFFSET_HI,tmp);
  682.         }
  683.     }
  684.  
  685. vga_driverspecs.setdisplaystart(address);
  686. }
  687.  
  688. static void mach32_setlogicalwidth(int width)
  689. {
  690. register int mywidth;
  691. #ifdef DEBUG
  692. printf("mach32_setlogicalwidth(%d)\n",width);
  693. #endif
  694. if(infotable[CM].bytesperpixel) /* always >= 1 for Mach32 modes */
  695.     {
  696.     /*Unfortunately the Mach32 expects this value in Pixels not bytes:*/
  697.     mywidth=width/(infotable[CM].bytesperpixel);
  698.     mywidth=(mywidth>>3)&0xff;
  699.     #ifdef DEBUG
  700.     printf("mach32_setlogicalwidth: Mach32 width to %d pels.\n",mywidth*8);
  701.     #endif
  702.     outw(CRT_PITCH,mywidth);
  703.     if(pitch_follows)
  704.         {
  705.         mach32_ge_pitch=mywidth;
  706.         if(mach32_accelstate==R_EXTENDED)
  707.             outw(GE_PITCH,mywidth);
  708.         }
  709.     }
  710.  
  711. vga_driverspecs.setlogicalwidth(width);
  712. }
  713.  
  714.  
  715. static void mach32_setpage(int page)
  716. {
  717. register unsigned short tmp;
  718.  
  719. #ifdef DEBUG
  720. printf("mach32_setpage(%d)\n",page);
  721. #endif
  722. if(mach32_pagemode!=PAGE_BOTH)
  723.     {
  724.     outb(ATIPORT,ATISEL(0x3E));
  725.     tmp=inb(ATIPORT+1)&0xf7;
  726.     tmp=(tmp<<8)|ATISEL(0x3E);
  727.     outw(ATIPORT,tmp);
  728.     mach32_pagemode=PAGE_BOTH;
  729.     }
  730. tmp=(page<<9)&0x1e00;
  731. outw(ATIPORT,ATISEL(0x32)|tmp);
  732. outb(ATIPORT,ATISEL(0x2e));
  733. tmp=(inb(ATIPORT+1)&0xfc)|((page>>4)&3);
  734. outw(ATIPORT,ATISEL(0x2e)|(tmp<<8));
  735. }
  736.  
  737. static void mach32_setwrpage(int page)
  738. {
  739. register unsigned short tmp;
  740. if(mach32_pagemode!=PAGE_DIFF)
  741.     {
  742.     outb(ATIPORT,ATISEL(0x3E));
  743.     outw(ATIPORT,(ATISEL(0x3E)<<8)|(inb(ATIPORT+1)|8));
  744.     mach32_pagemode=PAGE_DIFF;
  745.     }
  746. outb(ATIPORT,ATISEL(0x32));
  747. tmp=inb(ATIPORT+1)&0xe1;
  748. outw(ATIPORT,(ATISEL(0x32)<<8)|((page<<1)&0x1e));
  749. outb(ATIPORT,ATISEL(0x2e));
  750. tmp=inb(ATIPORT+1)&0xfc;
  751. outw(ATIPORT,(ATISEL(0x2e)<<8)|tmp|((page>>4)&3));
  752. }
  753.  
  754. static void mach32_setrdpage(int page)
  755. {
  756. register unsigned short tmp;
  757. if(mach32_pagemode!=PAGE_DIFF)
  758.     {
  759.     outb(ATIPORT,ATISEL(0x3E));
  760.     outw(ATIPORT,(ATISEL(0x3E)<<8)|(inb(ATIPORT+1)|8));
  761.     mach32_pagemode=PAGE_DIFF;
  762.     }
  763. outb(ATIPORT,ATISEL(0x32));
  764. tmp=inb(ATIPORT+1)&0x1e;
  765. if(page&8)
  766.     tmp|=1;
  767. outw(ATIPORT,(ATISEL(0x32)<<8)|tmp|((page<<5)&0xe0));
  768. outb(ATIPORT,ATISEL(0x2e));
  769. tmp=inb(ATIPORT+1)&0xf3;
  770. outw(ATIPORT,(ATISEL(0x2e)<<8)|tmp|((page>>2)&0xc));
  771. }
  772.  
  773. static void mach32_setappage(int page)
  774. {
  775. outw(MEM_CFG,(mach32_memcfg|(0xc&(page<<2))));
  776. }
  777.  
  778. static int mach32_sav_dac(int offset,unsigned char regs[])
  779. {
  780. /* I was unable to read out the actual DAC_config, so
  781. we just save which mode we are in: */
  782.  
  783. regs[offset]=mach32_dacmode;
  784. #ifdef DEBUG
  785. printf("mach32_sav_dac(%d,...): Dac:%d, dac_mode:%d\n",offset,mach32_dac,
  786.         regs[offset]);
  787. #endif
  788. return offset+1;
  789. }
  790.  
  791. static inline void clean_clocks(void)
  792. {
  793. outw(CLOCK_SEL,(inw(CLOCK_SEL)&~0x7f)|0x11);
  794. }
  795.  
  796. static int mach32_set_dac(int dac_mode, int clock_intended,int xres)
  797. {
  798. unsigned short act_ge_conf;
  799. const unsigned char *dac_reg;
  800.  
  801.  
  802. act_ge_conf=inw(R_EXT_GE_CONF)&0x8fff;
  803.  
  804. #ifdef DEBUG
  805. printf("mach32_set_dac(%d,%d): Dac:%d\n",dac_mode, clock_intended,mach32_dac);
  806. #endif
  807. mach32_dacmode=dac_mode;
  808. dac_mode&=0x7f;
  809. mach32_blankadj((mach32_dac==MACH32_ATI68830)?0x4:0xc);
  810. switch(mach32_dac)
  811.     {
  812.     case MACH32_SC11483:
  813.         dac_reg=mach32_dac1;
  814. #ifdef DEBUG
  815.             fputs("DAC1: ",stdout);
  816. #endif
  817.         if(dac_mode<=DAC_MODE565)
  818.             goto dac1_4;
  819.         break;
  820.     case MACH32_ATI6871:
  821.         /*This one is a nightmare: */
  822.         clean_clocks();
  823.         outw(EXT_GE_CONF,0x201a);
  824.  
  825.         switch(dac_mode)
  826.             {
  827.  
  828.             default:
  829.             case DAC_MODE8:
  830.             case DAC_MODEMUX:
  831.                 outb(DAC1,0x00);
  832.                 outb(DAC2,0x30);
  833.                 outb(DAC3,0x2d);
  834. #ifdef DEBUG
  835.                 puts("DAC2: 0x00 0x30 0x2d (8bpp)");
  836. #endif
  837.                 if(dac_mode!=DAC_MODEMUX)
  838.                     break;
  839.                 outb(DAC2,0x09);
  840.                 outb(DAC3,0x1d);
  841.                 outb(DAC1,0x01);
  842.                 mach32_blankadj(1);
  843. #ifdef DEBUG
  844.                 puts("DAC2: 0x01 0x09 0x1d (8bpp MUX)");
  845. #endif
  846.                 break;
  847.             case DAC_MODE555:
  848.             case DAC_MODE565:
  849.             case DAC_MODERGB:
  850.                 mach32_blankadj(1);
  851.             case DAC_MODE32B:
  852.                 outb(DAC1,0x01);
  853.                 if((!(clock_intended&0xc0))&&(!(mach32_dacmode&DAC_SEMICLK)))
  854.                     {
  855.                     outb(DAC2,0x00);
  856. #ifdef DEBUG
  857.                 puts("DAC2: 0x01 0x00 0x0d (16/24bpp)");
  858. #endif
  859.                     }
  860.                 else    {
  861.                     clock_intended&=0xff3f;
  862.                     outb(DAC2,0x08);
  863.                     mach32_dacmode|=DAC_SEMICLK;
  864.                     if(xres<=640)
  865.                         mach32_blankadj(2);
  866. #ifdef DEBUG
  867.                 puts("DAC2: 0x01 0x08 0x0d (16/24bpp)");
  868. #endif
  869.                     }
  870.                 outb(DAC3,0x0d);
  871.                 act_ge_conf|=0x4000;
  872.                 if(dac_mode==DAC_MODE32B)
  873.                     mach32_blankadj(3);
  874.                 break;
  875.             }
  876.         if(bladj>=0)
  877.             mach32_blankadj(bladj);
  878.         break;
  879.     case MACH32_BT481:
  880.         dac_reg=mach32_dac4;
  881. #ifdef DEBUG
  882.             fputs("DAC4: ",stdout);
  883. #endif
  884.         dac1_4:
  885.         if(dac_mode<=DAC_MODERGB)
  886.             {
  887.             clean_clocks();
  888.             outw(EXT_GE_CONF,0x101a);
  889. #ifdef DEBUG
  890.             printf("%02x\n",dac_reg[dac_mode]);
  891. #endif
  892.             outb(DAC2,dac_reg[dac_mode]);
  893.             }
  894.         break;
  895.     case MACH32_ATI68860:
  896.         clean_clocks();
  897.         outw(EXT_GE_CONF,0x301a);
  898. #ifdef DEBUG
  899.             printf("DAC5: %02x\n",mach32_dac5[dac_mode]);
  900. #endif
  901.         outb(DAC0,mach32_dac5[dac_mode]);
  902.         break;
  903.     }
  904. /*Dac RS2,3 to 0 */
  905. act_ge_conf&=0x8fff;
  906. if((dac_mode==DAC_MODE8)||(dac_mode==DAC_MODEMUX))
  907.     if(ext_settings&VGA_CLUT8)
  908.         act_ge_conf|=0x4000;
  909. outw(EXT_GE_CONF,act_ge_conf);
  910. /*Set appropriate DAC_MASK:*/
  911. switch(dac_mode)
  912.     {
  913.     case DAC_MODE8:
  914.     case DAC_MODEMUX:
  915. #ifdef DEBUG
  916.         puts("DAC-Mask to 0xff");
  917. #endif
  918.         outb(DAC_MASK,0xff);
  919.         break;
  920.     default:
  921.         switch(mach32_dac)
  922.             {
  923.             case MACH32_ATI6871:
  924.             case MACH32_BT481:
  925. #ifdef DEBUG
  926.                 puts("DAC-Mask to 0x00");
  927. #endif
  928.                 outb(DAC_MASK,0x00);
  929.                 break;
  930.             }
  931. #ifdef DEBUG
  932.         puts("VGA-DAC-Mask to 0x0f");
  933. #endif
  934.         outb(VGA_DAC_MASK,0x0f);
  935.         break;
  936.     }
  937. return clock_intended;
  938. }
  939.  
  940. static int mach32_saveregs(unsigned char regs[])
  941. {
  942. int i,retval;
  943. unsigned short tmp;
  944.  
  945. mach32_bltwait();     /* Ensure noone draws in the screen */
  946.  
  947. for(i=0;i<sizeof(mach32_eregs);i++)
  948.     {
  949.     outb(ATIPORT,ATISEL(mach32_eregs[i]));
  950.     regs[EXT+i]=inb(ATIPORT+1);
  951.     }
  952. regs[EXT+i]=mach32_disp_shadow; /* This is for DISP_CNTL */
  953. retval=i+EXT+1;
  954. for(i=0;i < ( sizeof(mach32_acc_regs) / sizeof(unsigned short) )  ; i+=2 )
  955.     {
  956.     tmp=inw(mach32_acc_regs[i]);
  957.     regs[retval++]=tmp;
  958.     regs[retval++]=(tmp>>8);
  959.     }
  960. retval=mach32_sav_dac(retval,regs);
  961. #ifdef DEBUG
  962. printf("mach32_saveregs: retval=%d\n",retval);
  963. #endif
  964. return retval-EXT;
  965. }
  966.  
  967. static int mach32_setregs(unsigned char regs[])
  968. {
  969. int i,offset,retval,clock_intended=0;
  970. unsigned short tmp;
  971.  
  972. mach32_bltwait();     /* Ensure noone draws in the screen */
  973. mach32_accelstate=R_UNKNOWN;    /* Accel registers need to be reset */
  974.  
  975. offset=EXT+sizeof(mach32_eregs)+( sizeof(mach32_acc_regs) / sizeof(unsigned short) )+1;
  976.  
  977. /*Find out which clock we want to use:*/
  978. for(i = ( sizeof(mach32_acc_regs) / sizeof(unsigned short) ) - 1, retval=offset; i>=0 ;
  979.     i-=2, retval-=2 )
  980.     if(mach32_acc_regs[i]==CLOCK_SEL)
  981.         {
  982.         clock_intended=((unsigned short)regs[--retval])<<8;
  983.         clock_intended|=regs[--retval];
  984.         break;
  985.         }
  986.  
  987. #ifdef DEBUG
  988. printf("mach32_setregs: offset=%d, clock_intended=%d\n",offset,clock_intended);
  989. #endif
  990.  
  991. retval=offset+1;
  992. mach32_set_dac(regs[offset],clock_intended,0);/*We can savely call with a fake xres coz
  993.                         blank adjust will be restored afterwards
  994.                         anyways...*/
  995.  
  996. for(i = ( sizeof(mach32_acc_regs) / sizeof(unsigned short) ) - 1 ; i>=0  ; i-=2 )
  997.     {
  998.     tmp=((unsigned short)regs[--offset])<<8;
  999.     tmp|=regs[--offset];
  1000.     /* restore only appage in MEM_CFG... otherwise badly interaction
  1001.        with X that may change MEM_CFG and does not only not restore it's
  1002.        original value but also insist on it not being changed on VC
  1003.        change... =:-o */
  1004.     if(mach32_acc_regs[i]==MEM_CFG)
  1005.         tmp=(inw(MEM_CFG)&~0xc)|(tmp&0xc);
  1006.     outw(mach32_acc_regs[i],tmp);
  1007.     }
  1008. mach32_disp_shadow=regs[--offset]&~0x60;
  1009. outb(DISP_CNTL,mach32_disp_shadow|0x40); /* Mach32 CRT reset */
  1010. if(inw(CLOCK_SEL)&1)    /* If in non VGA mode */
  1011.     outw(DISP_CNTL,mach32_disp_shadow|0x20); /* Mach32 CRT enabled */
  1012.  
  1013. for(i=sizeof(mach32_eregs)-1;i>=0;i--)
  1014.     {
  1015.     outb(ATIPORT,ATISEL(mach32_eregs[i]));
  1016.     outb(ATIPORT+1,regs[--offset]);
  1017.     }
  1018.  
  1019. return retval-EXT;
  1020. }
  1021.  
  1022. static int mach32_unlock(void)
  1023. {
  1024. unsigned short oldval;
  1025.  
  1026. #ifdef DEBUG
  1027. puts("mach32_unlock");
  1028. #endif /* DEBUG */
  1029. outb(ATIPORT,ATISEL(0x2e));
  1030. oldval=inb(ATIPORT+1)&~0x10;  /* Unlock CPUCLK Select */
  1031. outw(ATIPORT,ATISEL(0x2e)|(oldval<<8));
  1032.  
  1033. outb(ATIPORT,ATISEL(0x2b));
  1034. oldval=inb(ATIPORT+1)&~0x18;  /* Unlock DAC, Dbl Scan. */
  1035. outw(ATIPORT,ATISEL(0x2b)|(oldval<<8));
  1036.  
  1037. outb(ATIPORT,ATISEL(0x34));
  1038. oldval=inb(ATIPORT+1)&~0xfc; /* Unlock Crt9[0:4,7], Vtiming, Cursr start/end,
  1039.                 CRT0-7,8[0-6],CRT14[0-4]. but disable ignore of CRT11[7] */
  1040. outw(ATIPORT,ATISEL(0x34)|(oldval<<8));
  1041.  
  1042. outb(ATIPORT,ATISEL(0x38)); /* Unlock ATTR00-0f, ATTR11, whole vga, port 3c2 */
  1043. oldval=inb(ATIPORT+1)&~0x0f;
  1044. outw(ATIPORT,ATISEL(0x38)|(oldval<<8));
  1045.  
  1046. /* Unlock vga-memory too:*/
  1047.  
  1048. outw(MEM_BNDRY,0);
  1049.  
  1050. /* Unlock Mach32 CRT Shadowregisters... this one made me crazy...
  1051.    Thanx to the Xfree sources I finally figured it out....*/
  1052. outw(SHADOW_SET, 1);
  1053. outw(SHADOW_CTL, 0);
  1054. outw(SHADOW_SET, 2);
  1055. outw(SHADOW_CTL, 0);
  1056. outw(SHADOW_SET, 0);
  1057.  
  1058. return 0;
  1059. }
  1060.  
  1061. static int mach32_lock(void)
  1062. {
  1063. unsigned short oldval;
  1064.  
  1065. #ifdef DEBUG
  1066. puts("mach32_lock");
  1067. #endif /* DEBUG */
  1068. /* I'm really not sure if calling this function would be a good idea */
  1069. /* Actually it is not called in svgalib */
  1070. outb(ATIPORT,ATISEL(0x2b));
  1071. oldval=inb(ATIPORT+1)|0x18;  /* Lock DAC, Dbl Scan. */
  1072. outw(ATIPORT,ATISEL(0x2b)|(oldval<<8));
  1073.  
  1074. outb(ATIPORT,ATISEL(0x34));
  1075. oldval=inb(ATIPORT+1)|0xfc; /* Lock Crt9[0:4,7], Vtiming, Cursr start/end,
  1076.                 CRT0-7,8[0-6],CRT14[0-4]. but disable ignore of CRT11[7] */
  1077. outw(ATIPORT,ATISEL(0x34)|(oldval<<8));
  1078.  
  1079. outb(ATIPORT,ATISEL(0x38)); /* Lock ATTR00-0f, ATTR11, whole vga, port 3c2 */
  1080. oldval=inb(ATIPORT+1)|0x0f;
  1081. outw(ATIPORT,ATISEL(0x38)|(oldval<<8));
  1082.  
  1083. outw(SHADOW_SET, 1);
  1084. outw(SHADOW_CTL, 0x7f);
  1085. outw(SHADOW_SET, 2);
  1086. outw(SHADOW_CTL, 0x7f);
  1087. outw(SHADOW_SET, 0);
  1088.  
  1089. return 0;
  1090. }
  1091.  
  1092. static void mach32_experm(void)
  1093. {
  1094. printf("svgalib(mach32): Cannot get I/O permissions.\n");
  1095. exit(-1);
  1096. }
  1097.  
  1098. static int mach32_bltwait(void)
  1099. {
  1100. int i=BUSYWAIT;
  1101. clock_t clk_time;
  1102.  
  1103. checkqueue(16);    /* Ensure nothing in the queue */
  1104.  
  1105. while(i--)
  1106.     if(!(inw(GE_STAT) & (GE_BUSY | 1)))
  1107.         {
  1108.         done:
  1109.         /* Check additional stats */
  1110.         if(inw(SUBSYS_STAT)&4)
  1111.             goto failure;
  1112.         CRITICAL = 0; /* Obviously we're idle */
  1113.         return 0;
  1114.         }
  1115. clk_time=clock();
  1116.  
  1117. do      {
  1118.     if(!(inw(GE_STAT) & (GE_BUSY | 1)))
  1119.         goto done;
  1120.     }
  1121. while( (clock()-clk_time) < (CLOCKS_PER_SEC*ADDIWAIT) );
  1122.  
  1123. failure:
  1124. mach32_ge_reset();
  1125.  
  1126. return -1;
  1127. }
  1128.  
  1129. static void mach32_i_bltwait()
  1130. {
  1131. int i;
  1132.  
  1133. for (i=0; i < 100000; i++)
  1134.     if(!(inw(GE_STAT) & (GE_BUSY | 1)))
  1135.         break;
  1136. }
  1137.  
  1138. static int mach32_test()
  1139. {
  1140. int result=0;
  1141. short tmp;
  1142.  
  1143. /* If IOPERM is set, assume permissions have already been set by Olaf Titz' */
  1144. /* ioperm(1). */
  1145. if (getenv("IOPERM") == NULL)
  1146.     if(iopl(3)<0)
  1147.         mach32_experm();
  1148. /* Har, har.. now we can switch off interrupts to crash the system... ;-)=) */
  1149. /* (But actually we need only access to extended io-ports...) */
  1150.  
  1151. tmp = inw(SCRATCH_PAD_0);
  1152. outw(SCRATCH_PAD_0, 0x5555);
  1153. mach32_i_bltwait();
  1154. if(inw(SCRATCH_PAD_0) == 0x5555)
  1155.     {
  1156.     outw(SCRATCH_PAD_0, 0x2a2a);
  1157.     mach32_i_bltwait();
  1158.     if(inw(SCRATCH_PAD_0) == 0x2a2a)
  1159.         {
  1160.         /* Aha.. 8514/a detected.. */
  1161.         result=1;
  1162.         }
  1163.     }
  1164. outw(SCRATCH_PAD_0,tmp);
  1165. if(!result)
  1166.     goto quit;
  1167. /* Now ensure it is not a plain 8514/a: */
  1168. result=0;
  1169. outw(DESTX_DIASTP, 0xaaaa);
  1170. mach32_i_bltwait();
  1171. if(inw(R_SRC_X)==0x02aa)
  1172.     {
  1173.     outw(DESTX_DIASTP, 0x5555);
  1174.     mach32_i_bltwait();
  1175.     if(inw(R_SRC_X)==0x0555)
  1176.         result=1;
  1177.     }
  1178. if(!result)
  1179.     goto quit;
  1180. result=0;
  1181. /* Ok, now we have a Mach32. Unfortunately we need also the VGA to be enabled: */
  1182. if(inw(CONF_STAT1)&ONLY_8514)
  1183.     {
  1184.     if (__svgalib_driver_report)
  1185.         puts("Mach32 detected, but unusable with VGA disabled.\nSorry.\n");
  1186.     goto quit;    /*VGA circuitry disabled.*/
  1187.     }
  1188. result=1;
  1189. quit:
  1190. if(result)
  1191.     mach32_init(0,0,0);
  1192. else    iopl(0); /* safety */
  1193. #ifdef DEBUG
  1194. printf("mach32_test: returning %d.\n",result);
  1195. #endif /* DEBUG */
  1196. return result;
  1197. }
  1198.  
  1199. static void mach32_wait()
  1200. {
  1201. /* Wait for at least 22 us.. (got that out of a BIOS disassemble on my 486/50 ;-) ) ... */
  1202. register int i;
  1203. for(i=0;i<16;i++)
  1204.     dummy++;    /*Dummy is volatile..*/
  1205. }
  1206.  
  1207. static int mach32_eeclock(register int ati33)
  1208. {
  1209. outw(ATIPORT,ati33|=0x200);    /* clock on */
  1210. mach32_wait();
  1211. outw(ATIPORT,ati33&= ~0x200); /* clock off */
  1212. mach32_wait();
  1213. return ati33;
  1214. }
  1215.  
  1216. static void mach32_eekeyout(register int ati33, register int offset, register int mask)
  1217. {
  1218. do    {
  1219.     if(mask&offset)
  1220.         ati33|= 0x100;
  1221.     else    ati33&=~0x100;
  1222.     outw(ATIPORT,ati33);
  1223.     mach32_eeclock(ati33);
  1224.     }
  1225. while(mask>>=1);
  1226. }
  1227.  
  1228. static int mach32_eeget(int offset)
  1229. {
  1230. register int ati33;
  1231. register int result,i;
  1232.  
  1233. /* get current ATI33 */
  1234. outb(ATIPORT,ATISEL(0x33));
  1235. ati33=((int)inw(ATIPORT+1))<<8;
  1236. ati33|=ATISEL(0x33);
  1237. /* prepare offset.. cut and add header and trailer */
  1238. offset=(0x600|(offset&0x7f))<<1;
  1239.  
  1240. /* enable eeprom sequence */
  1241. ati33=mach32_eeclock(ati33);
  1242. /*input to zero..*/
  1243. outw(ATIPORT,ati33&=~0x100);
  1244. /*enable to one*/
  1245. outw(ATIPORT,ati33|= 0x400);
  1246. mach32_eeclock(ati33);
  1247. /*select to one*/
  1248. outw(ATIPORT,ati33|= 0x800);
  1249. mach32_eeclock(ati33);
  1250. mach32_eekeyout(ati33,offset,0x800);
  1251. for(i=0,result=0;i<16;i++)
  1252.     {
  1253.     result<<=1;
  1254.     outb(ATIPORT,ATISEL(0x37));
  1255.     if(inb(ATIPORT+1)&0x8)
  1256.         result|=1;
  1257.     mach32_eeclock(ati33);
  1258.     }
  1259. /*deselect...*/
  1260. outw(ATIPORT,ati33&=~0x800);
  1261. mach32_eeclock(ati33);
  1262. /*disable...*/
  1263. outw(ATIPORT,ati33&=~0x400);
  1264. mach32_eeclock(ati33);
  1265. return result;
  1266. }
  1267.  
  1268. static int mach32_max_mask(int x)
  1269. {
  1270. if(x<=0x4f)
  1271.     return dacmo640[mach32_dac];
  1272. if(x<=0x63)
  1273.     return dacmo800[mach32_dac];
  1274. if(x<=0x7f)
  1275.     return dacmo1024[mach32_dac];
  1276. return dacmo1280[mach32_dac];
  1277. }
  1278.  
  1279. static int mach32_max_vfifo16(int x)
  1280. {
  1281. int retval;
  1282.  
  1283. if(x<=0x63)
  1284.     retval=vfifo16;
  1285. else if(x<=0x7f)
  1286.     retval=vfifo16+4;
  1287. else    retval=vfifo16+5;
  1288. return (retval<15)?retval:15;
  1289. }
  1290.  
  1291. /* Shameless ripped out of Xfree2.1 (with slight changes) : */
  1292.  
  1293. static void mach32_scan_clocks(void)
  1294. {
  1295. const int knownind=7;
  1296. const double knownfreq=44.9;
  1297.  
  1298. char hstrt,hsync;
  1299. int htotndisp,vdisp,vtotal,vstrt,vsync,clck,i;
  1300.  
  1301. int count, saved_nice, loop;
  1302. double scale;
  1303.  
  1304. saved_nice=nice(0);
  1305. nice(-20 - saved_nice);
  1306.  
  1307. puts("Warning, about to measure clocks. Wait until system is completely idle!\n"
  1308.      "Any activity will disturb measuring, and therefor hinder correct driver\n"
  1309.      "function. Test will need about 3-4 seconds."
  1310.      "If your monitor doesn't switch off when it gets signals it can't sync on\n"
  1311.      "better switch it off now before continuing. I'll beep when you can safely\n"
  1312.      "switch it back on.");
  1313. #if 1
  1314. puts("\n(Enter Y<Return> to continue, any other text to bail out)");
  1315.  
  1316. if(getchar()!='Y')
  1317.     {
  1318.     bailout:
  1319.     puts("\aBailed out.");
  1320.     exit(0);
  1321.     }
  1322. if(getchar()!='\n')
  1323.     goto bailout;
  1324. #endif
  1325.  
  1326. htotndisp=inw(R_H_TOTAL);
  1327. hstrt=inb(R_H_SYNC_STRT);
  1328. hsync=inb(R_H_SYNC_WID);
  1329. vdisp=inw(R_V_DISP);
  1330. vtotal=inw(R_V_TOTAL);
  1331. vstrt=inw(R_V_SYNC_STRT);
  1332. vsync=inw(R_V_SYNC_WID);
  1333. clck=inw(CLOCK_SEL);
  1334.  
  1335. outb(DISP_CNTL,0x63);
  1336.  
  1337. outb(H_TOTAL,0x63);
  1338. outb(H_DISP,0x4f);
  1339. outb(H_SYNC_STRT,0x52);
  1340. outb(H_SYNC_WID,0x2c);
  1341. outw(V_TOTAL,0x418);
  1342. outw(V_DISP,0x3bf);
  1343. outw(V_SYNC_STRT,0x3d6);
  1344. outw(V_SYNC_WID,0x22);
  1345.  
  1346. for(i=0;i<16;i++)
  1347.     {
  1348.     outw(CLOCK_SEL, (i << 2) | 0xac1);
  1349.     outb(DISP_CNTL,0x23);
  1350.  
  1351.     usleep(MODESWITCHDELAY);
  1352.  
  1353.     count = 0;
  1354.     loop = 200000;
  1355.  
  1356.     while (!(inb(DISP_STATUS) & 2)) 
  1357.         if (loop-- == 0) goto done;
  1358.     while (inb(DISP_STATUS) & 2) 
  1359.         if (loop-- == 0) goto done;
  1360.     while (!(inb(DISP_STATUS) & 2)) 
  1361.         if (loop-- == 0) goto done;
  1362.     
  1363.     for (loop = 0; loop < 5; loop++) 
  1364.         {
  1365.         while (!(inb(DISP_STATUS) & 2)) 
  1366.             count++;
  1367.         while ((inb(DISP_STATUS) & 2)) 
  1368.             count++;
  1369.         }
  1370.     done:
  1371.     mach32_clocks[i]=count;
  1372.  
  1373.     outb(DISP_CNTL,0x63);
  1374.     }
  1375.  
  1376. outw(CLOCK_SEL,clck);
  1377.  
  1378. outw(H_DISP,htotndisp);
  1379. outb(H_SYNC_STRT,hstrt);
  1380. outb(H_SYNC_WID,hsync);
  1381. outw(V_DISP,vdisp);
  1382. outw(V_TOTAL,vtotal);
  1383. outw(V_SYNC_STRT,vstrt);
  1384. outw(V_SYNC_WID,vsync);
  1385. nice(20 + saved_nice);
  1386.  
  1387. /*Recalculation:*/
  1388. scale=((double)mach32_clocks[knownind])*knownfreq;
  1389. for(i=0;i<16;i++)
  1390.     {
  1391.     if(i==knownind)
  1392.         continue;
  1393.     if(mach32_clocks[i])
  1394.         mach32_clocks[i]=0.5+scale/((double)mach32_clocks[i]);
  1395.     }
  1396. mach32_clocks[knownind]=knownfreq+0.5;
  1397. }
  1398.  
  1399. static signed char mach32_search_clk(int clk)
  1400. {
  1401. int i;
  1402.  
  1403. if(!clk)
  1404.     return 0;
  1405. if(clk>80) /* Actually filter out the too high clocks here already */
  1406.     return 0;
  1407. for(i=0;i<32;i++)
  1408.     if(abs(clk-mach32_clocks[i])<=1)
  1409.         return i+1;
  1410. return 0;
  1411. }
  1412.  
  1413. static unsigned short dac14_clock_adjust(unsigned short clock,signed char *clock_map)
  1414. {
  1415. unsigned short clock_ind;
  1416.  
  1417. if((mach32_dac!=MACH32_SC11483)&&(mach32_dac!=MACH32_BT481))
  1418.     return clock;
  1419. clock_ind=0x1f&(clock>>2);
  1420. clock&= 0xff83;
  1421. if(!clock_map[clock_ind])
  1422.     {
  1423.     vga_setmode(TEXT);
  1424.     puts("svgalib-mach32: Panic, internal error: DAC1/4, invalid clock for >8bpp.");
  1425.     exit(1);
  1426.     }
  1427. return clock|((clock_map[clock_ind]-1)<<2);
  1428. }
  1429.  
  1430. static int mach32_init(int force, int chiptype, int memory)
  1431. {
  1432. char messbuf[12],eeapert=0;
  1433. static int max2msk[]={1,3,0xf,0xf};
  1434. static const short mem_conf[]={512,1024,2048,4096};
  1435. static const short mem_aper[]={0,
  1436.                          MACH32_APERTURE,
  1437.                          MACH32_APERTURE|MACH32_APERTURE_4M,
  1438.                          0};
  1439. int i;
  1440. unsigned short *ptr,cfg1,cfg2;
  1441. unsigned long apertloc=0;
  1442.  
  1443. #ifdef EXPERIMENTAL
  1444. if(getenv("EXPERIMENTAL") != NULL)
  1445.     {
  1446.     mach32_experimental=atoi(getenv("EXPERIMENTAL"));
  1447.     printf("mach32: EXPERIMENTAL set to: %04x\n",mach32_experimental);
  1448.     }
  1449. else    {
  1450.     printf("mach32: EXPERIMENTAL defaults to: %04x\n",mach32_experimental);
  1451.     }
  1452. #endif
  1453.  
  1454. /* If IOPERM is set, assume permissions have already been set by Olaf Titz' */
  1455. /* ioperm(1). */
  1456. if (getenv("IOPERM") == NULL)
  1457.     if(iopl(3)<0)
  1458.         mach32_experm();
  1459.  
  1460. mach32_readconfig();
  1461. /* Ensure we are idle. (Probable dead lock if no 8514 installed) */
  1462. mach32_bltwait();
  1463.  
  1464. /*get main config registers*/
  1465. cfg1=inw(CONF_STAT1);
  1466. cfg2=inw(CONF_STAT2);
  1467.  
  1468. /* get 2 eeprom buffers */
  1469. if(mach32_eeprom==NULL)
  1470.     {
  1471.     unsigned short sum,crea_eeprom=1;
  1472.  
  1473.     if((mach32_eeprom=malloc(sizeof(short)*2*128))==NULL)
  1474.         {
  1475.         printf("svgalib: mach32: Fatal error,\n"
  1476.             "not enough memory for EEPROM image (512 Bytes needed)\n");
  1477.         /* svgamode not yet set.. */
  1478.         exit(-1);
  1479.         }
  1480.     /* Do we have it already in a file ?*/
  1481.     if( (eeprom_fname!=NULL) && !(eeprom_option&EEPROM_UPDATE))
  1482.         {
  1483.         FILE *fd;
  1484.  
  1485.         fd=fopen(eeprom_fname,"rb");
  1486.         if(fd==NULL)
  1487.             {
  1488.             readerr:
  1489.             printf("mach32: Warning, can't access EEPROM file >%s<\nError was %d - %s\n",
  1490.                 eeprom_fname,errno,strerror(errno));
  1491.             goto read_eeprom;
  1492.             }
  1493.         if(1!=fread(mach32_eeprom,sizeof(short)*129,1,fd))
  1494.             {
  1495.             i=errno;
  1496.             fclose(fd);
  1497.             errno=i;
  1498.             goto readerr;
  1499.             }
  1500.         if(fclose(fd))
  1501.             goto readerr;
  1502.         /*Checksum..*/
  1503.         for(i=0,sum=0,ptr=mach32_eeprom;i<128;i++)
  1504.             sum+= *ptr++;
  1505.         if(sum == *ptr)
  1506.             {
  1507.             crea_eeprom=0; /*Mark succesful read...*/
  1508.             goto skip_read;    /* Use the read in file... */
  1509.             }
  1510.         sum=0;    /*Mark unsuccesful read..*/
  1511.         printf("mach32: Warning, EEPROM file >%s< corrupted.\n",eeprom_fname);
  1512.         }        
  1513.     
  1514.     /* Read in eeprom */
  1515.     read_eeprom:
  1516.     if( ! (eeprom_option & (EEPROM_USE_CHKSUM |
  1517.         EEPROM_USE_MEMCFG | EEPROM_USE_TIMING)) )
  1518.         {
  1519.         /* No need to bother reading the EEPROM */
  1520.         goto skip_read;
  1521.         }
  1522.     for(i=0,ptr=mach32_eeprom;i<128;i++)
  1523.         *ptr++ = mach32_eeget(i);
  1524.     if(eeprom_option & EEPROM_USE_CHKSUM)
  1525.         {
  1526.         for(i=0,sum=0,ptr=mach32_eeprom;i<128;i++)
  1527.             sum+= *ptr++;
  1528.         sum&=0xffff;
  1529.         if(sum)    {
  1530.             /*Hmm.. no ATI checksum... try AST:*/
  1531.             sum-= (mach32_eeprom[0x7f]<<1)-1;
  1532.             }
  1533.         }
  1534.     else    sum=0;
  1535.     if(sum&0xffff)
  1536.         {
  1537.         puts("mach32: Warning, Illegal checksum in Mach32 EEPROM.\n"
  1538.              "Check configuration of your card and read README.mach32,\n"
  1539.              "esp. the Mach32 Eeprom Woe chapter.\n"
  1540.              "Ignoring contents...");
  1541.         eeprom_option&= ~(EEPROM_USE_MEMCFG | EEPROM_USE_TIMING);
  1542.         }
  1543.     skip_read:
  1544.         
  1545.     if( (eeprom_fname!=NULL) && (crea_eeprom || (eeprom_option&EEPROM_UPDATE)) )
  1546.             /* create file if not there or unsuccesful or requested */
  1547.         {
  1548.         FILE *fd;
  1549.  
  1550.         /*Calc valid checksum..*/
  1551.         for(i=0,sum=0,ptr=mach32_eeprom;i<128;i++)
  1552.             sum+= *ptr++;
  1553.  
  1554.         fd=fopen(eeprom_fname,"wb");
  1555.         if(fd==NULL)
  1556.             {
  1557.             writerr:
  1558.             printf("mach32: Warning, can't create new EEPROM file >%s<\nError was %d - %s\n",
  1559.                 eeprom_fname,errno,strerror(errno));
  1560.             crea_eeprom=0;
  1561.             goto finish_w_eeprom;
  1562.             }
  1563.         if(1!=fwrite(mach32_eeprom,sizeof(short)*128,1,fd))
  1564.             {
  1565.             fwri_err:
  1566.             i=errno;
  1567.             fclose(fd);
  1568.             errno=i;
  1569.             goto writerr;
  1570.             }
  1571.         if(1!=fwrite(&sum,sizeof(short),1,fd))
  1572.             goto fwri_err;
  1573.         if(fclose(fd))
  1574.             goto writerr;
  1575.         printf("mach32: Notice: new EEPROM file >%s< succesful created.\n",
  1576.             eeprom_fname);
  1577.         finish_w_eeprom:
  1578.         }
  1579.     /* Change eeprom contents if requested: */
  1580.     if( ! (eeprom_option&EEPROM_USE_MEMCFG))
  1581.         mach32_eeprom[6]=0;
  1582.     if( ! (eeprom_option&EEPROM_USE_TIMING))
  1583.         {
  1584.         /* Consider ALL standard modes, but no user defined */
  1585.         mach32_eeprom[0x07]=0x01;    /*  640 x  480 */
  1586.         mach32_eeprom[0x08]=0x3f;    /*  640 x  480 */
  1587.         mach32_eeprom[0x09]=0x1f;    /*  640 x  480 */
  1588.         mach32_eeprom[0x0A]=0x03;    /*  640 x  480 */
  1589.         mach32_eeprom[0x0B]=0x00;    /*  no 1152x900 or 1120x750 */
  1590.         }
  1591.     if(!clocks_set)
  1592.         {
  1593.         char linebuffer[512];
  1594.  
  1595.         puts("mach32: Warning, no clocks defined.. please have a look at\n"
  1596.              "README.Mach32 and README.config for details.\n");
  1597.         mach32_scan_clocks();
  1598.         fputs("\a\nResulting clocks command for your libvga.config should be:\n\n"
  1599.             "clocks", stdout);
  1600.         for(i=0;i<16;i++)
  1601.                 printf(" %3d",mach32_clocks[i]);
  1602.         fputs("\n\nPlease edit \""
  1603.              SVGALIB_CONFIG_FILE
  1604.              "\" appropriately.\n"
  1605.              "Or shall I try to do it for you? You have to have write access to the\n"
  1606.              "config file to do it! (y/n) ",stdout);
  1607.         i=getchar();
  1608.         if(i!='\n')
  1609.             while(getchar()!='\n');
  1610.         if((i!='y')&&(i!='Y'))
  1611.             {
  1612.             puts("Ok, then do it yourself.");
  1613.             exit(0);
  1614.             }
  1615.         
  1616.         /* Toast setuid settings coz of security breach of system().. */
  1617.  
  1618.         setreuid(getuid(),getuid());
  1619.         setuid(getuid());
  1620.         setgid(getgid());
  1621.         
  1622.         strcpy(linebuffer,"rm -f "
  1623.                SVGALIB_CONFIG_FILE
  1624.                ".bak; mv "
  1625.                SVGALIB_CONFIG_FILE
  1626.                " "
  1627.                SVGALIB_CONFIG_FILE
  1628.                ".bak; echo clocks");
  1629.         for(i=0;i<16;i++)
  1630.                sprintf(strchr(linebuffer,0)," %d",mach32_clocks[i]);
  1631.         strcat(linebuffer," | cat - "
  1632.                SVGALIB_CONFIG_FILE
  1633.                ".bak >"
  1634.                SVGALIB_CONFIG_FILE);
  1635.         if(system(linebuffer))
  1636.             puts("Failed (at least partial, maybe there was just no config file yet).");
  1637.         else    puts("Ok. (But you should check it anyway)");
  1638.         exit(0);
  1639.         }
  1640.     #ifdef DEBUG
  1641.     printf("ATI-EEPROM contents:");
  1642.     for(i=0;i<128;i++)
  1643.         {
  1644.         if(i&7)
  1645.             putchar(' ');
  1646.         else    puts("");
  1647.         printf("%02x - %04x",i,mach32_eeprom[i]);
  1648.         }
  1649.     #ifdef DEBUG_KEY
  1650.     fputs("\n(Hit Return)",stdout);
  1651.     while(getchar()!='\n');
  1652.     #else
  1653.     putchar('\n');
  1654.     #endif /* DEBUG_KEY */
  1655.     #endif /* DEBUG */
  1656.     }
  1657. /*create a scratch copy.*/
  1658. memcpy(mach32_eeprom+128,mach32_eeprom,(size_t)(128*sizeof(short)));
  1659.  
  1660. /*Get current memcfg*/
  1661. mach32_memcfg=inw(MEM_CFG)&0xfff3;
  1662.  
  1663. /*If aperture not currently enabled but configured in EEPROM or setup already,
  1664.   then setup a faked setuplinear, switched off with setuplinear 0 0*/
  1665.  
  1666. if( (!(mach32_memcfg&3)) && (((mach32_eeprom[6] + 1) & 3) > 1) && (!mach32_apsiz) )
  1667.     {
  1668.     /*create setup from eeprom:*/
  1669.     mach32_apsiz=(mach32_eeprom[6]&3);
  1670.     mach32_apadd=(mach32_eeprom[6]>>4);
  1671.     eeapert=1;
  1672.     }
  1673. /*setup up memory aperture if requested:*/
  1674.  
  1675. if(mach32_apsiz)
  1676.     {
  1677.     unsigned new_memcfg;
  1678.  
  1679.     if(!mach32_apadd)
  1680.         mach32_memcfg=0;    /*disable any aperture*/
  1681.     else    {
  1682.         if( ((cfg1&BUS_TYPE)==PCI) || ((cfg2&Z4GBYTE)&& !(cfg2&LOCAL_BUS_CONF2)) )
  1683.             {
  1684.             /* 4GB address range... */
  1685.             new_memcfg=(mach32_apadd<<4)&0xfff0;
  1686.             i=4096;
  1687.             }
  1688.         else    {
  1689.             /* 128MB address range... */
  1690.             new_memcfg=(mach32_apadd<<8)&0xff00;
  1691.             i=128;
  1692.             }
  1693.         new_memcfg|=mach32_apsiz;
  1694.         if((cfg1&BUS_TYPE)==ISA)
  1695.             i=16;
  1696.         i-=mach32_apadd;
  1697.         i-=(mach32_apsiz==1)?1:4;
  1698.         if(i<0) {
  1699.             puts("svgalib-mach32: Dangerous warning:\n"
  1700.                          "\tsetuplinear setting exceeds phys. address range of card!\n"
  1701.                  "\tSetting ignored.");
  1702.             mach32_apsiz=0;
  1703.             }
  1704.         else    {
  1705.             /* will be actually set by setappage(0) call in setmode */
  1706.             mach32_memcfg=new_memcfg;
  1707.             }
  1708.         }
  1709.     }
  1710.  
  1711. mach32_dac=(cfg1>>9)&7;
  1712. mach32_chiptype=mem_aper[mach32_memcfg&3];
  1713. if(!force)
  1714.     mach32_memory=mem_conf[(inw(MISC_OPTIONS)>>2)&3];
  1715. else    {
  1716.     mach32_memory=memory;
  1717.     if(chiptype&MACH32_FORCEDAC)
  1718.         mach32_dac=chiptype&0xf;
  1719.     if(chiptype&MACH32_FORCE_APERTURE)
  1720.         {
  1721.         mach32_chiptype=(chiptype&(MACH32_APERTURE|MACH32_APERTURE_4M));
  1722.         if(mach32_chiptype&MACH32_APERTURE_4M)
  1723.             mach32_chiptype|=MACH32_APERTURE;
  1724.         }
  1725.     }
  1726. if(mach32_dac>5)
  1727.     {
  1728.     printf("mach32: Warning, unknown DAC type: %d. Assuming stupid 8bpp DAC rated at 80Mhz!\n",
  1729.         mach32_dac);
  1730.     /* Assumption is already done in all tables used... */
  1731.     }
  1732. if(!(DAC_SAFETY&(1<<mach32_dac)))
  1733.     {
  1734.     char *cptr;
  1735.     /* Safety notification */
  1736.     cptr=getenv("SVGALIB_MACH32");
  1737.     if(cptr==NULL)
  1738.         {
  1739.         messexit:
  1740.         puts("\aWarning!! The mach32 driver of svgalib was never tried with a DAC type\n"
  1741.                "!=2,0. Nevertheless, I put every knowledge I got from the DOCs in this\n"
  1742.                "driver, so it should work. If you think you can stand this risk\n"
  1743.                "(for example, your monitor will just switch off if he can't stand the\n"
  1744.                "video signal) then set the environment variable SVGALIB_MACH32 to\n"
  1745.                "ILLTRYIT or --- of course --- recompile svgalib after changing the\n"
  1746.                "#define DAC_SAFETY in mach32.c\n\n"
  1747.                "To reduce possibility of damage to your card you should check that no\n"
  1748.                "video mode above 80Mhz dotclock is used with dacs !=2 or 5. To check\n"
  1749.                "recompile with DEBUG defined in mach32.c and look at the output.\n"
  1750.                "In any case, that is, if it works or not (and what went wrong),\n"
  1751.                "please tell me about:\n"
  1752.                "Michael Weller, eowmob@exp-math.uni-essen.de,\n"
  1753.                "eowmob@pollux.exp-math.uni-essen.de, or mat42b@aixrs1.hrz.uni-essen.de.\n.");
  1754.         exit(-1);
  1755.         }
  1756.     if(strcmp(cptr,"ILLTRYIT"))
  1757.         goto messexit;
  1758.     }
  1759. if(mach32_dac!=2)
  1760.     pos_ext_settings&= ~VGA_CLUT8;
  1761.     
  1762.  
  1763. /* Access aperture */
  1764. if((mach32_chiptype&MACH32_APERTURE)&&(mach32_aperture==NULL))
  1765.     {
  1766.     if( ((cfg1&BUS_TYPE)==PCI) || ((cfg2&Z4GBYTE)&& !(cfg2&LOCAL_BUS_CONF2)) )
  1767.         {
  1768.         /* 4GB address range... */
  1769.         apertloc=((unsigned long)(mach32_memcfg&0xfff0))<<16;
  1770.         }
  1771.     else    {
  1772.         /* 128MB address range... */
  1773.         apertloc=((unsigned long)(mach32_memcfg&0xff00))<<12;
  1774.         }
  1775. #ifdef DEBUG
  1776.     printf("mach32: Physical aperture starts at %08lx.\n", apertloc);
  1777. #endif
  1778.     mach32_aperture=(char *)mmap((caddr_t)0x40000000,
  1779.         (mach32_chiptype&MACH32_APERTURE_4M)?4194304:1048576,
  1780.         PROT_READ|PROT_WRITE,
  1781.         MAP_SHARED|MAP_FIXED,
  1782.         __svgalib_mem_fd,
  1783.         apertloc);
  1784.     /* I trust the comment about memory waste in vgamisc.c...*/
  1785.     if(((long)mach32_aperture)<0)
  1786.         {
  1787.         i=errno;
  1788.         printf("mach32: Mmaping of aperture failed.\nError was %d",i);
  1789.         errno=i;
  1790.         perror(" - ");
  1791.         exit(-1);
  1792.         }
  1793. #ifdef DEBUG
  1794.     printf("mach32: Aperture mapped to %08lx.\n", (long)mach32_aperture);
  1795. #endif
  1796.     }
  1797. driverspecs = &mach32_driverspecs;
  1798.  
  1799. /* Check if imageblit emulation possible: */
  1800. i=0;
  1801. if(mach32_chiptype&MACH32_APERTURE_4M)
  1802.     i=(4<<10);
  1803. else if(mach32_chiptype&MACH32_APERTURE)
  1804.     i=(1<<10);
  1805. if(i<mach32_memory)
  1806.     { /*aperture to small*/
  1807.     emuimage&= ~(EMU_OVER|EMU_POSS);
  1808.     }
  1809. if(!mach32_modes)
  1810.     {
  1811.     mach32_modes=malloc( __svgalib_max_modes * sizeof(mode_entry *));
  1812.     if(!mach32_modes)
  1813.         {
  1814.         puts("mach32: No memory for dynamic mode table.");
  1815.         exit(1);
  1816.         }
  1817.     }
  1818.  
  1819. /*Calculate the double and triple clocks */
  1820. for(i=0;i<32;i++)
  1821.     mach32_clock_by2[i]=mach32_search_clk(mach32_clocks[i]<<1);
  1822. for(i=0;i<32;i++)
  1823.     mach32_clock_by3[i]=mach32_search_clk(mach32_clocks[i]*3);
  1824.  
  1825. #ifdef DEBUG
  1826. puts("15/16bpp DAC1/4 clock_maps:");
  1827. for(i=0;i<32;i++)
  1828.     {
  1829.     if(!(i&7))
  1830.         putchar('\n');
  1831.     if(mach32_clock_by2[i])
  1832.         printf("%3d->%3d  ",mach32_clocks[i],mach32_clocks[mach32_clock_by2[i]-1]);
  1833.     else    printf("%3d->  -  ",mach32_clocks[i]);
  1834.     }
  1835. puts("\n24bpp DAC1/4 clock_maps:");
  1836. for(i=0;i<32;i++)
  1837.     {
  1838.     if(!(i&7))
  1839.         putchar('\n');
  1840.     if(mach32_clock_by3[i])
  1841.         printf("%3d->%3d  ",mach32_clocks[i],mach32_clocks[mach32_clock_by3[i]-1]);
  1842.     else    printf("%3d->  -  ",mach32_clocks[i]);
  1843.     }
  1844. putchar('\n');
  1845. #endif
  1846.  
  1847. /*Populating database:*/
  1848. if(verbose)
  1849.     puts("Populating mode table:");
  1850.  
  1851. for(i=0;i<__svgalib_max_modes;i++)
  1852.     mach32_modes[i]=NULL;
  1853.  
  1854. for(i=0;i<NUM_MODES;i++)
  1855.     {
  1856.     if((predef_modes[i].offset==0)||
  1857.         (mach32_eeprom[predef_modes[i].offset]&predef_modes[i].mask))
  1858.         mach32_modfill(predef_modes+i,mach32_max_mask(predef_modes[i].h_disp),-1);
  1859.     }
  1860.  
  1861. if(mach32_eeprom[7]&2)
  1862.     {
  1863.     i=(mach32_eeprom[7]>>8)&0xff;
  1864.     if((mach32_eeprom[i]&0x140)==0x140)
  1865.         mach32_modfill((mode_entry *)(mach32_eeprom+i+2),
  1866.             max2msk[3&(mach32_eeprom[i]>>9)],-1);
  1867.     }
  1868. if(mach32_eeprom[8]&0x80)
  1869.     {
  1870.     i=(mach32_eeprom[8]>>8)&0xff;
  1871.     if((mach32_eeprom[i]&0x140)==0x140)
  1872.         mach32_modfill((mode_entry *)(mach32_eeprom+i+2),
  1873.             max2msk[3&(mach32_eeprom[i]>>9)],-1);
  1874.     }
  1875. if(mach32_eeprom[9]&0x80)
  1876.     {
  1877.     i=(mach32_eeprom[9]>>8)&0xff;
  1878.     if((mach32_eeprom[i]&0x140)==0x140)
  1879.         mach32_modfill((mode_entry *)(mach32_eeprom+i+2),
  1880.             max2msk[3&(mach32_eeprom[i]>>9)],-1);
  1881.     }
  1882. if(mach32_eeprom[10]&0x80)
  1883.     {
  1884.     i=(mach32_eeprom[10]>>8)&0xff;
  1885.     if((mach32_eeprom[i]&0x140)==0x140)
  1886.         mach32_modfill((mode_entry *)(mach32_eeprom+i+2),
  1887.             max2msk[3&(mach32_eeprom[i]>>9)],-1);
  1888.     }
  1889.  
  1890. if(verbose)
  1891.     puts("Squeeze in run-time config:");
  1892. mach32_final_modefixup();
  1893.  
  1894. if(__svgalib_driver_report)
  1895.     {
  1896.     sprintf(messbuf," at %dM",(int)(apertloc>>20));
  1897.     printf("Using Mach32 driver 2.0 (%s apert%s (%s), %dK mem, DAC %d%s).\n",
  1898.         (mach32_chiptype&MACH32_APERTURE) ?
  1899.              ((mach32_chiptype&MACH32_APERTURE_4M)?"4M":"1M")
  1900.              : "no",
  1901.         (mach32_chiptype&MACH32_APERTURE) ? messbuf : "",
  1902.         mach32_apsiz?(eeapert?"EEPROM":"setup"):"autodetect",
  1903.         mach32_memory,mach32_dac,force?", forced":"");
  1904.     }
  1905. return 0;
  1906. }
  1907.  
  1908. static inline int col2msk(struct info *iptr)
  1909. {
  1910. switch(iptr->colors)
  1911.     {
  1912.     case 1<<24:
  1913.         if(iptr->bytesperpixel==3)
  1914.             return 4;
  1915. #ifdef SUPP_32BPP
  1916.         if(iptr->bytesperpixel==4)
  1917.             return 8;
  1918. #endif
  1919.         else    return 0;
  1920.     case 1<<15:
  1921.     case 1<<16:
  1922.         if(iptr->bytesperpixel==2)
  1923.             return 2;
  1924.         else    return 0;
  1925.     case 256:
  1926.         if(iptr->bytesperpixel==1)
  1927.             return 1;
  1928.         else    return 0;
  1929.     }
  1930. return 0;
  1931. }
  1932.  
  1933. static inline int col2bypp(struct info *iptr)
  1934. {
  1935. return iptr->bytesperpixel;
  1936. }
  1937.  
  1938. static int mach32_log2(struct info *iptr)
  1939. {
  1940. int res= -1,n=iptr->colors;
  1941.  
  1942. while(n){
  1943.     res++;
  1944.     n>>=1;
  1945.     }
  1946. if((res==24) && (iptr->bytesperpixel==4))
  1947.     return 32;
  1948. return res;
  1949. }
  1950.  
  1951. static void mach32_modfill(const mode_entry * mode, int modemask, int forcein)
  1952. {
  1953. register int i;
  1954. register struct info *iptr;
  1955. register unsigned wid,hei;
  1956.  
  1957. float horz,vert,n_horz,n_vert;
  1958. int clock,n_clock,tmp;
  1959.  
  1960. clock=mach32_clocks[n_clock=0x1f&(mode->clock_sel>>2)];
  1961. if(!clock)
  1962.     {
  1963.     if(verbose)
  1964.         puts("Illegal clock #%d of unknown frequency! (rejected)");
  1965.     return;
  1966.     }
  1967. horz=(1e3*clock)/(float)(mode->h_total*8+8);
  1968. hei=mode->v_total;
  1969. if(!(mode->disp_cntl&0x6))
  1970.     hei=((hei>>2)&0xfffe)|(hei&1);
  1971. else    hei=((hei>>1)&0xfffc)|(hei&3);
  1972. hei++;
  1973. vert=(horz*1000)/hei;
  1974.  
  1975. wid=mode->h_disp*8+8;
  1976. hei=mode->v_disp;
  1977. if(!(mode->disp_cntl&0x6))
  1978.     hei=((hei>>2)&0xfffe)|(hei&1);
  1979. else    hei=((hei>>1)&0xfffc)|(hei&3);
  1980. hei++;
  1981.  
  1982.  
  1983. /*Maskout impossible colorsettings for high clock rates:*/
  1984. i=modemask;
  1985. modemask&=mach32_mmask[(clock>80)?1:0][mach32_dac];
  1986. if(verbose&&(i!=modemask))
  1987.     {
  1988.     printf("Modemask (32bpp,24bpp,16bpp,8bpp) %x cut down to %x by DAC restrictions.\n",i,modemask);
  1989.     }
  1990.  
  1991. /*Check if needed multiples are available*/
  1992. if((mach32_dac==MACH32_BT481)||(mach32_dac==MACH32_SC11483))
  1993.     {
  1994.     if((modemask&2)&&(!mach32_clock_by2[n_clock]))
  1995.         {
  1996.         modemask&= ~2;
  1997.         if(verbose)
  1998.             printf("DAC1/4: There is no clock with two times the requested\n"
  1999.                 "\tfreq. of %dMHz => no 15 or 16 bpp.\n",clock);
  2000.         }
  2001.     if((mach32_dac==MACH32_BT481)&&(modemask&4)&&(!mach32_clock_by3[n_clock]))
  2002.         {
  2003.         modemask&= ~4;
  2004.         if(verbose)
  2005.             printf("DAC4: There is no clock with three times the requested\n"
  2006.                 "\tfreq. of %dMHz => no 24bpp.\n",clock);
  2007.         }
  2008.     }
  2009.  
  2010. i=modemask;
  2011. /*Rate down clocks exceeding mem bandwidth*/
  2012. if(clock>mach32_maxclk8)
  2013.     modemask&=~1;
  2014. if(clock>mach32_maxclk16)
  2015.     modemask&=~2;
  2016. if(clock>mach32_maxclk24)
  2017.     modemask&=~4;
  2018. if(clock>mach32_maxclk32)
  2019.     modemask&=~8;
  2020.  
  2021. if(verbose&&(i!=modemask))
  2022.     printf("Modemask (32bpp,24bpp,16bpp,8bpp) %x cut down to %x by maxclocks.\n",i,modemask);
  2023.  
  2024. if(forcein>=0)
  2025.     {
  2026.     /*Well hack the next loop to run exactly one time for i=forcein..*/
  2027.     /*I know it's dirty...*/
  2028.     i=forcein;
  2029.     iptr=infotable+i;
  2030.     goto jumpin;    /*Show that to a Pascal coder and he falls down dead..*/
  2031.     }
  2032. for(i=0,iptr=infotable;(i<__svgalib_max_modes)&&(forcein<0);i++,iptr++)
  2033.     {
  2034.     jumpin:
  2035.     if((iptr->xdim!=wid)||(iptr->ydim!=hei)|| !(modemask&col2msk(iptr)))
  2036.         continue;
  2037.     if(verbose)
  2038.         {
  2039.         printf("%4ux%4ux%2u: ",
  2040.         wid,hei,mach32_log2(iptr));
  2041.         printf("%3d MHz Clock, %6.3f KHz horz., %6.3f Hz vert.,\n\t %s, VFIFO(16-%d,24-%d)",
  2042.             clock,horz,vert,
  2043.             (mode->disp_cntl&0x10)?"Interlaced":"Non-Interlaced",
  2044.             mode->vfifo16,mode->vfifo24);
  2045.         }
  2046.     if(iptr->xbytes*iptr->ydim >mach32_memory*1024)
  2047.         {
  2048.         if(verbose)
  2049.             puts(" (not enough memory)");
  2050.         continue;
  2051.         }
  2052.     if(__svgalib_monitortype<6)
  2053.         if(mach32_monitor[__svgalib_monitortype]<horz)
  2054.             {
  2055.             if(verbose)
  2056.                 puts(" (rejected, monitor safety)");
  2057.             continue;
  2058.             }
  2059.     if((mach32_modes[i]==NULL)||(forcein>=0))
  2060.         {
  2061.         if(verbose)
  2062.             puts(" (accepted)");
  2063.         fillin:
  2064.         mach32_modes[i]=mode;
  2065.         continue;
  2066.         }
  2067.     if((mach32_modes[i]->disp_cntl^mode->disp_cntl)&0x10)
  2068.         {
  2069.         if(mode->disp_cntl&0x10)
  2070.             {
  2071.             if(verbose)
  2072.                 puts(" (rejected, is interlaced)");
  2073.             continue;
  2074.             }
  2075.         else    {
  2076.             if(verbose)
  2077.                 puts(" (preferred, is non-interlaced)");
  2078.             goto fillin;
  2079.             }
  2080.         }
  2081.     n_clock=mach32_clocks[0x1f&(mach32_modes[i]->clock_sel>>2)];
  2082.     n_horz=(1e3*n_clock)/(float)(mach32_modes[i]->h_total*8+8);
  2083.     tmp=mach32_modes[i]->v_total;
  2084.     if(!(mach32_modes[i]->disp_cntl&0x6))
  2085.         tmp=((tmp>>2)&0xfffe)|(tmp&1);
  2086.     else    tmp=((tmp>>1)&0xfffc)|(tmp&3);
  2087.     tmp++;
  2088.     n_vert=(n_horz*1000)/tmp;
  2089.     if(n_vert<vert)
  2090.         {
  2091.         if(verbose)
  2092.             puts(" (higher V_SYNC preferred)");
  2093.         goto fillin;
  2094.         }
  2095.     if(verbose)
  2096.         puts(" (rejected, have a better one already)");
  2097.     }
  2098. }
  2099.  
  2100. static int mach32_modeavailable(int mode)
  2101. {
  2102. if(mode>__svgalib_max_modes)
  2103.     return 0;
  2104. if(mach32_modes[mode]==NULL)
  2105.     return vga_driverspecs.modeavailable(mode);
  2106. return SVGADRV;
  2107. }
  2108.  
  2109. static int mach32_getmodeinfo(int mode,vga_modeinfo *modeinfo)
  2110. {
  2111. if(mode>__svgalib_max_modes)
  2112.     return 0;
  2113. modeinfo->flags|=HAVE_EXT_SET;
  2114. modeinfo->haveblit=0;
  2115.  
  2116. if(mach32_modes[mode]==NULL)
  2117.     return 0;
  2118.  
  2119. if(infotable[mode].bytesperpixel<=2)
  2120.     modeinfo->haveblit=acc_supp;
  2121. else if(emuimage&EMU_POSS)
  2122.     { /* imageblt can be emulated with memory aperture */
  2123.     modeinfo->haveblit=acc_supp&HAVE_IMAGEBLIT;
  2124.     }
  2125.  
  2126. modeinfo->flags|=(HAVE_RWPAGE|EXT_INFO_AVAILABLE);
  2127. if(mach32_modes[mode]->disp_cntl&0x10)
  2128.     modeinfo->flags|=IS_INTERLACED;
  2129.  
  2130. if(modeinfo->colors==256)
  2131.     modeinfo->linewidth_unit=8;
  2132. else if(modeinfo->colors==(1<<24))
  2133.     {
  2134.     modeinfo->linewidth_unit=(PIXALIGN*infotable[mode].bytesperpixel);
  2135.     if(infotable[mode].bytesperpixel==4)
  2136.         modeinfo->flags|=RGB_MISORDERED;
  2137.     }
  2138. else    modeinfo->linewidth_unit=(PIXALIGN*2);
  2139.  
  2140. modeinfo->bytesperpixel=infotable[mode].bytesperpixel;
  2141. modeinfo->linewidth=infotable[mode].xbytes;
  2142. modeinfo->maxlogicalwidth=0xff*8*modeinfo->bytesperpixel;
  2143.  
  2144. /* This is obsolete.. modeinfo->bytesperpixel should always be > 0 here */
  2145. if (modeinfo->bytesperpixel > 0)
  2146.     {
  2147.     modeinfo->maxpixels=(mach32_memory*1024)/modeinfo->bytesperpixel;
  2148.     }
  2149. else    {
  2150.     modeinfo->maxpixels=(mach32_memory*1024);
  2151.     }
  2152.  
  2153. modeinfo->startaddressrange=0xfffffffc&(mach32_memory*1024-1);
  2154.  
  2155. modeinfo->chiptype=mach32_dac|(mach32_chiptype&(MACH32_APERTURE_4M|MACH32_APERTURE));
  2156. if(mach32_chiptype&MACH32_APERTURE_4M)
  2157.     modeinfo->aperture_size=(4<<10);
  2158. else if(mach32_chiptype&MACH32_APERTURE)
  2159.     modeinfo->aperture_size=(1<<10);
  2160. else modeinfo->aperture_size=0;
  2161. modeinfo->memory=mach32_memory;
  2162. if(modeinfo->aperture_size>=mach32_memory)
  2163.     modeinfo->flags|=CAPABLE_LINEAR;
  2164. modeinfo->linear_aperture=(char *)mach32_aperture;
  2165. modeinfo->set_aperture_page=mach32_setappage;
  2166. modeinfo->extensions=(mach32_eeprom+128);
  2167.  
  2168. return 1;
  2169. }
  2170.  
  2171. static void mach32_blankadj(int adj)
  2172. {
  2173. #ifdef DEBUG
  2174. printf("mach32_blankadj(%d)\n",adj);
  2175. #endif
  2176. outb(MISC_CTL+1,(inb(R_MISC_CTL+1)&0xf0)|adj);
  2177. }
  2178.  
  2179. static int mach32_setmode(int mode, int previous)
  2180. {
  2181. register const mode_entry *mptr;
  2182. int type,clock,clock_intended,vfifo;
  2183. unsigned short act_ge_conf;
  2184.  
  2185. type=mach32_modeavailable(mode);
  2186. if(!type)
  2187.     return 1;
  2188.  
  2189. #ifdef DEBUG
  2190. printf("mach32_setmode: %d -> %d\n",previous,mode);
  2191. #endif
  2192.  
  2193. if(mach32_modeavailable(previous)==SVGADRV)
  2194.     mach32_bltwait();     /* Ensure noone draws in the screen */
  2195.  
  2196. mach32_accelstate=R_UNKNOWN;    /* Accel registers need to be reset */
  2197.  
  2198. #ifdef DEBUG
  2199. puts("mach32_setmode: accel set.");
  2200. #endif
  2201.  
  2202. if(type!=SVGADRV)
  2203.     {
  2204.     #ifdef DEBUG
  2205.     printf("mach32_setmode: standard mode:%d\n",mode);
  2206.     #endif
  2207.  
  2208.     /*if imageblit works at all, it'll be this one:*/
  2209.     mach32_driverspecs.imageblt = mach32_memimageblt;
  2210.  
  2211.     /*Set std dac-mode*/
  2212.     mach32_set_dac(DAC_MODE8,0,0);
  2213.  
  2214.     /* Ensure we are in VGA-mode: */
  2215.     outw(CLOCK_SEL,(inw(CLOCK_SEL)&~0x7f)|0x10); /* slow clock and disable
  2216.                                 Mach CRT */
  2217.     outw(DISP_CNTL,mach32_disp_shadow|0x40); /* Mach32 CRT reset */
  2218.  
  2219.     /* Force all extended ati regs to std. vga mode. This is needed for
  2220.        correct function when using non standard console text modes.*/
  2221.         {
  2222.         int i;
  2223.         const unsigned char *ptr;
  2224.         unsigned int val;
  2225.  
  2226.         /* Stop vga sequencer: */
  2227.         outb(SEQ_I,0x00);
  2228.         outb(SEQ_D,0x00);
  2229.  
  2230.         /* Handle the important reg 0x38: clock-diff by 2, no herc emul */
  2231.  
  2232.         outb(ATIPORT,ATISEL(0x38));
  2233.         val=(inb(ATIPORT+1)&0x1f)|0x40;
  2234.         outw(ATIPORT,ATISEL(0x38)|(val<<8));
  2235.  
  2236.         /* Handle the important reg 0x39: Select some clock */
  2237.  
  2238.         outb(ATIPORT,ATISEL(0x39));
  2239.         val=(inb(ATIPORT+1)&0xfc)|0x02;
  2240.         outw(ATIPORT,ATISEL(0x39)|(val<<8));
  2241.  
  2242.         for(i=0,ptr=mach32_ati_ext;i < (sizeof(mach32_ati_ext)/2) ;i++,ptr+=2)
  2243.             {
  2244.             outb(ATIPORT,ATISEL(*ptr));
  2245.             val=inb(ATIPORT+1)& ~ptr[1];
  2246.             outw(ATIPORT,ATISEL(*ptr)|(val<<8));
  2247.             }
  2248.  
  2249.         /* sequencer is reenabled by vga setmode */
  2250.         }
  2251.     
  2252.     return vga_driverspecs.setmode(mode);
  2253.     /* vga_setmode will ensure vga is on...*/
  2254.     }
  2255. else    {
  2256.     /* handle the selection of imageblit */
  2257.     if( (infotable[mode].colors!=(1<<24)) /* mode is supported by engine */
  2258.         && (!(emuimage&EMU_OVER)) /* and should not be overridden */
  2259.             )
  2260.         mach32_driverspecs.imageblt = mach32_imageblt;
  2261.     else
  2262.         mach32_driverspecs.imageblt = mach32_memimageblt;
  2263.     }
  2264.  
  2265. /*switch off vga for better mem access and to fake setpalette.....*/
  2266. /*vga_screenoff(); Actually vga_setmode did this already.... and vga_screenon
  2267. is already disabled..*/
  2268.  
  2269. #ifdef DEBUG
  2270. printf("mach32_setmode: Setting vga in 8bpp graphmode.\n");
  2271. #endif
  2272.  
  2273. /*Ripped out from Xfree.. mach32 Server..*/
  2274. outw(SEQ_I, 4 | (0x0a << 8));
  2275. /* Enable write access to all memory maps */
  2276. outw(SEQ_I, 2 | (0x0f << 8));
  2277. /* Set linear addressing mode */
  2278. outw(ATIPORT, ATISEL(0x36) | (0x05 << 8));
  2279. /* Set the VGA display buffer to 0xa0000 */
  2280. outw(GRA_I, 6 | (0x05 << 8));
  2281. /*These are mine...someone turned the VGA to erase on write....(Eeeek!)*/
  2282. outw(GRA_I, 1 | (0x00 << 8));
  2283. outw(GRA_I, 3 | (0x00 << 8));
  2284. outw(GRA_I, 5 | (0x00 << 8));
  2285. outw(GRA_I, 7 | (0x00 << 8));
  2286. outw(GRA_I, 8 | (0xff << 8));
  2287. /*Switch on any videomemory latches we have:*/
  2288. outw(MISC_OPTIONS,(inw(MISC_OPTIONS)&0x8f7f)|(latchopt&0x7080));
  2289. #ifdef DEBUG
  2290. printf("mach32_setmode: extended mode:%d\n",mode);
  2291. #endif
  2292.  
  2293. mptr=mach32_modes[mode];
  2294.  
  2295. mach32_disp_shadow=mptr->disp_cntl&0x7f;
  2296. outw(DISP_CNTL,mach32_disp_shadow|0x60); /* Mach32 CRT reset */
  2297. outw(MULTI_FUNC_CNTL,0x5006);    /* Linear memory layout */
  2298. /*set dac: */
  2299.  
  2300. clock_intended=mptr->clock_sel;
  2301. clock=mach32_clocks[0x1f&(clock_intended>>2)];
  2302.  
  2303. switch(infotable[mode].colors)
  2304.     {
  2305.     default:    /* 256 */
  2306.         clock_intended=mach32_set_dac((clock>80)?DAC_MODEMUX:DAC_MODE8,
  2307.                     clock_intended,infotable[mode].xdim);
  2308.         act_ge_conf=inw(R_EXT_GE_CONF)&0xf80f;
  2309.         if(clock>80)
  2310.             act_ge_conf|=0x0110;
  2311.         else    act_ge_conf|=0x0010;
  2312.         /* Force VFIFO in clock_sel to zero:*/
  2313.         clock_intended&=0xf0ff;
  2314.         clock_intended|=(vfifo8<<8);
  2315.         break;
  2316.     case 1<<15:
  2317.         clock_intended=mach32_set_dac(DAC_MODE555,
  2318.             dac14_clock_adjust(clock_intended,mach32_clock_by2),
  2319.             infotable[mode].xdim);
  2320.         act_ge_conf=inw(R_EXT_GE_CONF)&0xf80f;
  2321.         act_ge_conf|=0x0020;
  2322.         /* Force VFIFO in clock_sel to zero:*/
  2323.         clock_intended&=0xf0ff;
  2324.         vfifo=max(mptr->vfifo16,mach32_max_vfifo16(infotable[mode].xdim));
  2325.         clock_intended|=(vfifo<<8);
  2326.         break;
  2327.     case 1<<16:
  2328.         clock_intended=mach32_set_dac(DAC_MODE565,
  2329.             dac14_clock_adjust(clock_intended,mach32_clock_by2),
  2330.             infotable[mode].xdim);
  2331.         act_ge_conf=inw(R_EXT_GE_CONF)&0xf80f;
  2332.         act_ge_conf|=0x0060;
  2333.         /* Force VFIFO in clock_sel to zero:*/
  2334.         clock_intended&=0xf0ff;
  2335.         vfifo=max(mptr->vfifo16,mach32_max_vfifo16(infotable[mode].xdim));
  2336.         clock_intended|=(vfifo<<8);
  2337.         break;
  2338.     case 1<<24:
  2339.         clock_intended=mach32_set_dac(
  2340.             (infotable[mode].bytesperpixel==3)?DAC_MODERGB:DAC_MODE32B,
  2341.                 dac14_clock_adjust(clock_intended,mach32_clock_by3),
  2342.                 infotable[mode].xdim);
  2343.         act_ge_conf=inw(R_EXT_GE_CONF)&0xf80f;
  2344.         if(infotable[mode].bytesperpixel==3)
  2345.             {
  2346.             act_ge_conf|=0x0030;
  2347.             vfifo=max(mptr->vfifo24,vfifo24);
  2348.             }
  2349. #ifdef SUPP_32BPP
  2350.         else    {
  2351. #ifdef USE_RGBa
  2352.             act_ge_conf|=0x0630;
  2353. #else
  2354.             act_ge_conf|=0x0230;
  2355. #endif
  2356.             vfifo=max(mptr->vfifo24,vfifo32);
  2357.             }
  2358. #endif
  2359.         /* Force VFIFO in clock_sel to zero:*/
  2360.         clock_intended&=0xf0ff;
  2361.         clock_intended|=(vfifo<<8);
  2362.         break;
  2363.     }
  2364. outw(EXT_GE_CONF,act_ge_conf);
  2365. /*Set clock and disable VGA... those pinheads from ATI have the clock
  2366.   settings in all their tables with the VGA enabled....Gee..*/
  2367. clock_intended|=1;
  2368.  
  2369. #ifdef DEBUG
  2370. printf("GE_CONF:%hx\n",act_ge_conf);
  2371. printf("Setting mode:\th_disp: %x\th_total: %x\th_sync_wid: %x\th_sync_strt: %x\t"
  2372. "v_disp: %x\tv_total: %x\tv_sync_wid: %x\tv_sync_strt: %x\tclock_sel: %x\tdisp_ctl: %x\n",
  2373. mptr->h_disp,mptr->h_total,mptr->h_sync_wid,mptr->h_sync_strt,mptr->v_disp,mptr->v_total,
  2374. mptr->v_sync_wid,mptr->v_sync_strt,clock_intended,mach32_disp_shadow);
  2375. #endif
  2376. outb(H_TOTAL,mptr->h_total);
  2377. outw(H_DISP,mptr->h_disp);
  2378. outb(H_SYNC_STRT,mptr->h_sync_strt);
  2379. outb(H_SYNC_WID,mptr->h_sync_wid);
  2380. outw(V_TOTAL,mptr->v_total);
  2381. outw(V_DISP,mptr->v_disp);
  2382. outw(V_SYNC_STRT,mptr->v_sync_strt);
  2383. outw(V_SYNC_WID,mptr->v_sync_wid);
  2384.  
  2385. #ifdef DEBUG
  2386.     outw(CLOCK_SEL,clock_intended);
  2387. #else
  2388.     outw(CLOCK_SEL,clock_intended&~1); /*Screen does not show up yet..
  2389.                         will be fired up by final vga_screenon
  2390.                         called from setmode (still time to
  2391.                         erase the screen.. ;) */
  2392. #endif
  2393.  
  2394. mach32_setlogicalwidth(infotable[mode].xbytes);
  2395. mach32_setdisplaystart(0);
  2396. mach32_setappage(0);    /* This sets up a requested mem aperture too.. */
  2397.  
  2398. outw(DISP_CNTL,mach32_disp_shadow|0x20); /* Mach32 CRT enable */
  2399.  
  2400. #if defined(DEBUG_KEY)&&defined(DEBUG)
  2401.     fputs("\n(Hit Return)",stdout);
  2402.     while(getchar()!='\n');
  2403. #endif
  2404. return 0;
  2405. }
  2406.  
  2407. static short *push(int num)
  2408. {
  2409. short *ptr;
  2410.  
  2411. if(mixup_ptr+num>=mixup_alloc)
  2412.     {
  2413.     if(mach32_modemixup==NULL)
  2414.         mach32_modemixup=malloc(PREALLOC*sizeof(short));
  2415.     else    mach32_modemixup=realloc(mach32_modemixup,(mixup_alloc+=PREALLOC)*sizeof(short));
  2416.     if(mach32_modemixup==NULL)
  2417.         {
  2418.         puts("mach32-config: Fatal error: Out of memory.");
  2419.         exit(-1);
  2420.         }
  2421.     }
  2422. ptr=mach32_modemixup+mixup_ptr;
  2423. mixup_ptr+=num;
  2424. return ptr;
  2425. }
  2426.  
  2427. static int isnumber(char *str)
  2428. {
  2429. if(str==NULL)
  2430.     return 0;
  2431. return strlen(str)==strspn(str,"0123456789");
  2432. }
  2433.  
  2434. static int parsemode(char *str,int linelength,int create)
  2435. {
  2436. char tmpstr[6], *ptr;
  2437. int i;
  2438. unsigned width,height,colors, bytesperpixel;
  2439.  
  2440. if(!str)
  2441.     return -1;
  2442. for(ptr=str;*ptr;ptr++)
  2443.     *ptr=tolower(*ptr);
  2444. if(sscanf(str,"%ux%ux%5s",&width,&height,tmpstr)!=3)
  2445.     return -1;
  2446. if(!strcmp(tmpstr,"256")) {
  2447.     colors=256;
  2448.     bytesperpixel = 1;
  2449. }
  2450. else if(!strcmp(tmpstr,"32k")) {
  2451.     colors=(1<<15);
  2452.     bytesperpixel = 2;
  2453. }
  2454. else if(!strcmp(tmpstr,"64k")) {
  2455.     colors=(1<<16);
  2456.     bytesperpixel = 2;
  2457. }
  2458. else if(!strcmp(tmpstr,"16m")) {
  2459.     colors=(1<<24);
  2460.     bytesperpixel = 3;
  2461. }
  2462. #ifdef SUPP_32BPP
  2463. else if(!strcmp(tmpstr,"16m32")) {
  2464.     colors=(1<<24);
  2465.     bytesperpixel = 4;
  2466. }
  2467. else if(!strcmp(tmpstr,"16m4")) {    /* compatibility */
  2468.     colors=(1<<24);
  2469.     bytesperpixel = 4;
  2470. }
  2471. #endif
  2472. else    {
  2473.     printf("mach32-config: mode %s unsupported, only 256, 32K, 64K, 16M, 16M32 colors allowed.\n",tmpstr);
  2474.     return -2;
  2475.     }
  2476. width=(width+7)&~7;
  2477. if(linelength<width)
  2478.     linelength=width;
  2479. else    linelength=(linelength+7)&~7;
  2480.  
  2481. linelength *= bytesperpixel;
  2482.  
  2483. for(i=0;i<__svgalib_max_modes;i++)
  2484.     {
  2485.     if((infotable[i].xdim==width)&&(infotable[i].ydim==height)&&
  2486.             (infotable[i].colors==colors)&&(infotable[i].bytesperpixel==bytesperpixel))
  2487.         {
  2488.         infotable[i].xbytes=linelength;
  2489.         return i;
  2490.         }
  2491.     }
  2492. if(!create)
  2493.     return -2;
  2494. if((i=__vga_addmode(width,height,colors,linelength,bytesperpixel))<0)
  2495.     {
  2496.     printf("mach32-config: no more dynamic modes, %s ignored.\n",tmpstr);
  2497.     return -2;
  2498.     }
  2499. return i;
  2500. }
  2501.  
  2502. static inline unsigned int mach32_skip2(unsigned int vtime)
  2503. {
  2504. return ((vtime<<1)&0xfff8)|(vtime&3)|((vtime&0x80)>>5);
  2505. }
  2506.  
  2507. static char *mach32_procopt(int command,int mode) {
  2508. mode_entry *mptr;
  2509. char *ptr;
  2510. int i,currptr,flag;
  2511.  
  2512. switch(command)
  2513.     {
  2514.     case 0:
  2515.         {
  2516.         int position=0; /* We are handling the POSITION-th parameter */
  2517.  
  2518.         if(!mode)
  2519.             {
  2520.             puts("mach32-config: mach32eeprom command access denied.");
  2521.             break;
  2522.             }
  2523.         for(;;)    {
  2524.             position++;
  2525.             ptr=strtok(NULL," ");
  2526.             if(ptr==NULL)
  2527.                 {
  2528.                 if(position<=1)
  2529.                     puts("mach32-config: mach32eeprom "
  2530.                         "command expects a parameter.");
  2531.                 return ptr;
  2532.                 }
  2533.             if(!strcasecmp(ptr,"compatible"))
  2534.                 { 
  2535.                 eeprom_option|=EEPROM_USE_CHKSUM |
  2536.                         EEPROM_USE_MEMCFG | EEPROM_USE_TIMING;
  2537.                 }
  2538.             else if(!strcasecmp(ptr,"ignore"))
  2539.                 {
  2540.                 eeprom_option&= ~( EEPROM_USE_CHKSUM |
  2541.                            EEPROM_USE_MEMCFG | EEPROM_USE_TIMING );
  2542.                 }
  2543.             else if(!strcasecmp(ptr,"useaperture"))
  2544.                 {
  2545.                 eeprom_option|=EEPROM_USE_MEMCFG;
  2546.                 }
  2547.             else if(!strcasecmp(ptr,"usetimings"))
  2548.                 {
  2549.                 eeprom_option|=EEPROM_USE_TIMING;
  2550.                 }
  2551.             else if(!strcasecmp(ptr,"nofile"))
  2552.                 {
  2553.                 eeprom_fname=NULL;
  2554.                 }
  2555.             else if(!strcasecmp(ptr,"updatefile"))
  2556.                 {
  2557.                 eeprom_option|=EEPROM_UPDATE;
  2558.                 }
  2559.             else if(!strcasecmp(ptr,"keepfile"))
  2560.                 {
  2561.                 eeprom_option&= ~EEPROM_UPDATE;
  2562.                 }
  2563.             else if(!strcasecmp(ptr,"file"))
  2564.                 {
  2565.                 ptr=strtok(NULL," ");
  2566.                 if(ptr==NULL)
  2567.                     {
  2568.                     puts("mach32-config: mach32eeprom file subcommand "
  2569.                         "expects a parameter.");
  2570.                     return ptr;
  2571.                     }
  2572.                 goto fileparam;
  2573.                 }
  2574.             else if(position==1)
  2575.                 {
  2576.                 fileparam:
  2577.                 if(*ptr=='/')
  2578.                     {
  2579.                     if(eeprom_fname!=NULL)
  2580.                         free(eeprom_fname);
  2581.                     eeprom_fname=strdup(ptr);
  2582.                     if(eeprom_fname==NULL)
  2583.                         {
  2584.                         puts("mach32-config: Fatal error: out of memory.");
  2585.                         exit(-1);
  2586.                         }
  2587.                     }
  2588.                 else    {
  2589.                     puts("mach32-config: mach32eeprom: filename has "
  2590.                         "to start with a / !!");
  2591.                     }
  2592.                 }
  2593.             else    return ptr;
  2594.             }
  2595.         }
  2596.         break;
  2597.     case 1:
  2598.         for(;;)    {
  2599.             ptr=strtok(NULL," ");
  2600.             i=parsemode(ptr,0,0);
  2601.             if(i== -1)
  2602.                 return ptr;
  2603.             if(i>=0)
  2604.                 *push(1)=CMD_DEL+i;
  2605.             }
  2606.         break;
  2607.     case 2:    /* Define a new mode.. */
  2608.         currptr=mixup_ptr;
  2609.         flag=0;
  2610.         for(;;)    {
  2611.             ptr=strtok(NULL," ");
  2612.             i=parsemode(ptr,0,1);
  2613.             if(i== -1)
  2614.                 break;
  2615.             if(i>=0)
  2616.                 {
  2617.                 *push(1)=CMD_ADD+i;
  2618.                 flag=1;
  2619.                 }
  2620.             }
  2621.         if(!flag)
  2622.             {
  2623.             puts("mach32-config: Invalid define command, no valid vga-mode given");
  2624.             ex_inv_mod:
  2625.             mixup_ptr=currptr;
  2626.             return ptr;
  2627.             }
  2628.         *push(1)=CMD_MOD;
  2629.         mptr=(mode_entry *)push(SOMOD_SH);
  2630.         /* Read the mode in, this is almost like Xconfig.. */
  2631.         /*The clock is the only thing that may differ:*/
  2632.         if(ptr==NULL)
  2633.             {
  2634.             inv_clk:
  2635.             puts("mach32-config: Invalid define command, clock is invalid");
  2636.             goto ex_inv_mod;
  2637.             }
  2638.         if(*ptr==':')    /*No. of clock given*/
  2639.             {
  2640.             if(!isnumber(ptr+1))
  2641.                 goto inv_clk;
  2642.             i=atoi(ptr+1);
  2643.             }
  2644.         else    { /* search clock in table */
  2645.             if(!isnumber(ptr))
  2646.                 goto inv_clk;
  2647.             flag=atoi(ptr);
  2648.             for(i=0;i<32;i++)
  2649.                 if(flag==mach32_clocks[i])
  2650.                     break;
  2651.             }
  2652.         if(i>31)
  2653.             goto inv_clk;
  2654.         mptr->clock_sel=(i<<2);
  2655. #ifdef DEBUG
  2656. printf("Constructed clock_sel is: %d\n",mptr->clock_sel);
  2657. #endif
  2658.         mptr->disp_cntl=0x23; /* Assume non interlaced*/
  2659.         /* The rest is straight forward: */
  2660.         ptr=strtok(NULL," ");
  2661.         if(!isnumber(ptr))
  2662.             {
  2663.             inv_time:
  2664.             puts("mach32-config: Invalid define command, timing is invalid");
  2665.             goto ex_inv_mod;
  2666.             }
  2667.         mptr->h_disp=(atoi(ptr)>>3)-1;
  2668.         ptr=strtok(NULL," ");
  2669.         if(!isnumber(ptr))
  2670.             goto inv_time;
  2671.         i=atoi(ptr);
  2672.         mptr->h_sync_strt=(i>>3)-1;
  2673.         ptr=strtok(NULL," ");
  2674.         if(!isnumber(ptr))
  2675.             goto inv_time;
  2676.         mptr->h_sync_wid=((atoi(ptr)-i)>>3);
  2677.         if(mptr->h_sync_wid>0x1f)
  2678.             mptr->h_sync_wid=0x1f;
  2679.         ptr=strtok(NULL," ");
  2680.         if(!isnumber(ptr))
  2681.             goto inv_time;
  2682.         mptr->h_total=(atoi(ptr)>>3)-1;
  2683.  
  2684.         ptr=strtok(NULL," ");
  2685.         if(!isnumber(ptr))
  2686.             goto inv_time;
  2687.         mptr->v_disp=mach32_skip2(atoi(ptr)-1);
  2688.         ptr=strtok(NULL," ");
  2689.         if(!isnumber(ptr))
  2690.             goto inv_time;
  2691.         i=atoi(ptr);
  2692.         mptr->v_sync_strt=mach32_skip2(i-1);
  2693.         ptr=strtok(NULL," ");
  2694.         if(!isnumber(ptr))
  2695.             goto inv_time;
  2696.         mptr->v_sync_wid=atoi(ptr)-i;
  2697.         if(mptr->v_sync_wid>0x1f)
  2698.             mptr->v_sync_wid=0x1f;
  2699.         ptr=strtok(NULL," ");
  2700.         if(!isnumber(ptr))
  2701.             goto inv_time;
  2702.         mptr->v_total=mach32_skip2(atoi(ptr)-1);
  2703.         for(;;)    {    /* Parse for additional goodies */
  2704.             ptr=strtok(NULL," ");
  2705.             if(!strcasecmp(ptr,"interlace"))
  2706.                 mptr->disp_cntl|=0x10;
  2707.             else if(!strcasecmp(ptr,"+hsync"))
  2708.                 mptr->h_sync_wid&=~0x20;
  2709.             else if(!strcasecmp(ptr,"-hsync"))
  2710.                 mptr->h_sync_wid|=0x20;
  2711.             else if(!strcasecmp(ptr,"+vsync"))
  2712.                 mptr->v_sync_wid&=~0x20;
  2713.             else if(!strcasecmp(ptr,"-vsync"))
  2714.                 mptr->v_sync_wid|=0x20;
  2715.             else    break;
  2716.             }
  2717.         /*final fixup*/
  2718.         if(mptr->h_disp>0x4f)    /* x>640 */
  2719.             {
  2720.             mptr->vfifo24=0xe;
  2721.             if(mptr->h_disp>0x7f)
  2722.                 mptr->vfifo16=0xe;
  2723.             else if(mptr->h_disp>0x63)
  2724.                 mptr->vfifo16=0xd;
  2725.             else    mptr->vfifo16=0x9;
  2726.             }
  2727.         else    {
  2728.             mptr->vfifo16=0;
  2729.             mptr->vfifo24=0;
  2730.             }
  2731.         return ptr;    
  2732.     case 3:
  2733.         ptr=strtok(NULL," ");
  2734.         if(!isnumber(ptr))
  2735.             {
  2736.             puts("mach32-config: illegal setlinelength command.\n"
  2737.                 "Usage: setlinelength integer modes...");
  2738.             return ptr;
  2739.             }
  2740.         i=atoi(ptr);
  2741.         do    ptr=strtok(NULL," ");
  2742.         while(parsemode(ptr,i,0) != -1);
  2743.         return ptr;
  2744.     case 4:
  2745.         ptr=strtok(NULL," ");
  2746.  
  2747.         if(!mode)
  2748.             {
  2749.             maxclk_deny:
  2750.             puts("Don't use the maxclock's commands out of the environment variable.");
  2751.             return ptr;
  2752.             }
  2753.         
  2754.         if(!isnumber(ptr))
  2755.             {
  2756.             ilmaxclk:
  2757.             puts("mach32-config: illegal maxclock16 or maxclock24 command.\n"
  2758.                 "Usage: maxclock16 integer or maxclock24 integer");
  2759.             return ptr;
  2760.             }
  2761.         mach32_maxclk16=atoi(ptr);
  2762.         break;
  2763.     case 5:
  2764.         ptr=strtok(NULL," ");
  2765.         if(!mode)
  2766.             goto maxclk_deny;
  2767.         if(!isnumber(ptr))
  2768.             goto ilmaxclk;
  2769.         mach32_maxclk24=atoi(ptr);
  2770.         break;
  2771.     case 6:
  2772.         if(!mode)
  2773.             puts("mach32-config: clocks command denied.");
  2774.         for(i=0;i<16;i++)
  2775.             {
  2776.             ptr=strtok(NULL," ");
  2777.             clocks_set=1;
  2778.             if(!isnumber(ptr))
  2779.                 {
  2780.                 puts("mach32-config: illegal clocks command.\n"
  2781.                     "Usage: clocks integer integer ...\n"
  2782.                     "16 clocks have to be specified.\n"
  2783.                     "specify 0 for unsupported clocks\n"
  2784.                     "(using 0's for the mistyped clocks)");
  2785.                 if(mode){
  2786.                     while(i<16)
  2787.                         mach32_clocks[i++]=0;
  2788.                     /*Set halfed clocks:*/
  2789.                     for(i=0;i<16;i++)
  2790.                         mach32_clocks[i+16]=mach32_clocks[i]/2;
  2791.                     }
  2792.                 return ptr;
  2793.                 }
  2794.             if(mode)
  2795.                 mach32_clocks[i]=atoi(ptr);
  2796.             }
  2797.         /*Set halfed clocks:*/
  2798.         for(i=0;i<16;i++)
  2799.             mach32_clocks[i+16]=mach32_clocks[i]/2;
  2800.         break;
  2801.     case 7:
  2802.         mach32_strictness=0;
  2803.         break;
  2804.     case 8:
  2805.         mach32_strictness=1;
  2806.         break;
  2807.     case 9:
  2808.         mach32_strictness=2;
  2809.         break;
  2810.     case 10:
  2811.         ptr=strtok(NULL," ");
  2812.         if(!mode)
  2813.             goto maxclk_deny;
  2814.         if(!isnumber(ptr))
  2815.             goto ilmaxclk;
  2816.         mach32_maxclk8=atoi(ptr);
  2817.         break;
  2818.     case 11:
  2819.         ptr=strtok(NULL," ");
  2820.         if(!mode)
  2821.             goto maxclk_deny;
  2822.         if(!isnumber(ptr))
  2823.             goto ilmaxclk;
  2824.         mach32_maxclk32=atoi(ptr);
  2825.         break;
  2826.     case 12:
  2827.         verbose=1;
  2828.         break;
  2829.     case 13:
  2830. #ifndef DEBUG
  2831.         verbose=0;
  2832. #endif
  2833.         break;
  2834.     case 14:
  2835.         ptr=strtok(NULL," ");
  2836.         if(!mode)
  2837.             {
  2838.             tweak_deny:
  2839.             puts("The vfifo, latch, blank commands are not allowed out of the environment.");
  2840.             return ptr;
  2841.             }
  2842.         if(!isnumber(ptr))
  2843.             {
  2844.             ilvfi:
  2845.             puts("Illegal vfifo command");
  2846.             return ptr;
  2847.             }
  2848.         vfifo8=atoi(ptr)&0xf;
  2849.         break;
  2850.     case 15:
  2851.         ptr=strtok(NULL," ");
  2852.         if(!mode)
  2853.             goto tweak_deny;
  2854.         if(!isnumber(ptr))
  2855.             {
  2856.             puts("Illegal latch command");
  2857.             return ptr;
  2858.             }
  2859.         latchopt=atoi(ptr);
  2860.         break;
  2861.     case 16:
  2862.         ptr=strtok(NULL," ");
  2863.         if(!mode)
  2864.             goto tweak_deny;
  2865.         if(!isnumber(ptr))
  2866.             {
  2867.             puts("Illegal blank command");
  2868.             return ptr;
  2869.             }
  2870.         bladj=atoi(ptr)&0xf;
  2871.         break;
  2872.     case 17:
  2873.         ptr=strtok(NULL," ");
  2874.         if(!mode)
  2875.             goto tweak_deny;
  2876.         if(!isnumber(ptr))
  2877.             goto ilvfi;
  2878.         vfifo16=atoi(ptr)&0xf;
  2879.         break;
  2880.     case 18:
  2881.         ptr=strtok(NULL," ");
  2882.         if(!mode)
  2883.             goto tweak_deny;
  2884.         if(!isnumber(ptr))
  2885.             goto ilvfi;
  2886.         vfifo24=atoi(ptr)&0xf;
  2887.         break;
  2888.     case 19:
  2889.         ptr=strtok(NULL," ");
  2890.         if(!mode)
  2891.             goto tweak_deny;
  2892.         if(!isnumber(ptr))
  2893.             goto ilvfi;
  2894.         vfifo32=atoi(ptr)&0xf;
  2895.         break;
  2896.     case 20:
  2897.         ptr=strtok(NULL," ");
  2898.         if(!isnumber(ptr))
  2899.             {
  2900.             ilsetupli:
  2901.             puts("Illegal setuplinear command.\n"
  2902.                  "usage: setuplinear address size\n"
  2903.                  "where size = 1 or 4 and both are in MB");
  2904.             return ptr;
  2905.             }
  2906.         i=atoi(ptr);
  2907.         ptr=strtok(NULL," ");
  2908.         if(!strcmp(ptr,"4"))
  2909.             flag=1;
  2910.         else if(!strcmp(ptr,"1"))
  2911.             flag=0;
  2912.         else if(!strcmp(ptr,"0"))
  2913.             {
  2914.             flag=0;
  2915.             i=0;
  2916.             goto setuplin;
  2917.             }
  2918.         else goto ilsetupli;
  2919.         if((i&~0xfff)||(!i))
  2920.             {
  2921.             puts("setuplinear: address out of range");
  2922.             return ptr;
  2923.             }
  2924.         setuplin:
  2925.         if(!mode)
  2926.             {
  2927.             puts("setuplinear config option strictly disallowed from the environment.");
  2928.             return ptr;
  2929.             }
  2930.         mach32_apsiz=flag+1;
  2931.         mach32_apadd=i;    
  2932.         break;    
  2933.     case 21:
  2934.         for(;;)    {
  2935.             ptr=strtok(NULL," ");
  2936.             if(!strcasecmp(ptr,"bit"))
  2937.                 acc_supp|=HAVE_BITBLIT;
  2938.             else if(!strcasecmp(ptr,"nobit"))
  2939.                 acc_supp&=~HAVE_BITBLIT;
  2940.             else if(!strcasecmp(ptr,"fill"))
  2941.                 acc_supp|=HAVE_FILLBLIT;
  2942.             else if(!strcasecmp(ptr,"nofill"))
  2943.                 acc_supp&=~HAVE_FILLBLIT;
  2944.             else if(!strcasecmp(ptr,"image"))
  2945.                 {
  2946.                 acc_supp|=HAVE_IMAGEBLIT;
  2947.                 emuimage&=~EMU_OVER;
  2948.                 }
  2949.             else if(!strcasecmp(ptr,"noimage"))
  2950.                 {
  2951.                 acc_supp&=~HAVE_IMAGEBLIT;
  2952.                 }
  2953.             else if(!strcasecmp(ptr,"memimage"))
  2954.                 {
  2955.                 acc_supp|=HAVE_IMAGEBLIT;
  2956.                 emuimage|=EMU_OVER|EMU_POSS;
  2957.                 }
  2958.             else if(!strcasecmp(ptr,"nomemimage"))
  2959.                 {
  2960.                 emuimage&=~(EMU_OVER|EMU_POSS);
  2961.                 }
  2962.             else if(!strcasecmp(ptr,"hlinelist"))
  2963.                 acc_supp|=HAVE_HLINELISTBLIT;
  2964.             else if(!strcasecmp(ptr,"nohlinelist"))
  2965.                 acc_supp&=~HAVE_HLINELISTBLIT;
  2966.             else    return ptr;
  2967.             }
  2968.     }
  2969. return strtok(NULL," ");
  2970. }
  2971.  
  2972. static char *mach32_conf_commands[]={
  2973.     "mach32eeprom","inhibit","define","setlinelength","maxclock16",
  2974.     "maxclock24","clocks","variablelinelength","strictlinelength","duplicatelinelength",
  2975.     "maxclock8","maxclock32","verbose","quiet","vfifo8",
  2976.     "latch","blank","vfifo16","vfifo24","vfifo32",
  2977.     "setuplinear","blit",
  2978.         NULL};
  2979.  
  2980. static void mach32_readconfig(void)
  2981. {
  2982. static int conf_read=0;
  2983. int i,j,limit,newxbytes;
  2984.  
  2985. if(conf_read)
  2986.     return;
  2987. conf_read=1;
  2988.  
  2989. /*Hack info table.. see comment at start of file*/
  2990. for(i=0;i<__svgalib_max_modes;i++)
  2991.     {
  2992.     if(infotable[i].bytesperpixel<2)
  2993.         continue;    /* Not needed for those.. also excludes STDVGA non MACH32 modes */
  2994.     j=infotable[i].xdim%PIXALIGN;
  2995.     if(j)    infotable[i].xbytes+=infotable[i].bytesperpixel*(PIXALIGN-j);
  2996.     }
  2997. __svgalib_read_options(mach32_conf_commands,mach32_procopt);
  2998. if(mach32_strictness) /* Do something about the modes where we redefined xbytes.. */
  2999.     {
  3000.     limit=GLASTMODE;
  3001.     for(i=G640x480x256;i<limit;i++) /* leave the non SVGA modes alone */
  3002.         {
  3003.         if(!col2bypp(infotable+i))
  3004.             continue;    /* Don't deal with non mach32-modes */
  3005.         if(infotable[i].xbytes!=infotable[i].xdim*col2bypp(infotable+i)) /* mode was redefined */
  3006.             {
  3007.             newxbytes=infotable[i].xbytes;
  3008.             /*Let infotable[i] look like a virgin again:*/
  3009.             infotable[i].xbytes=infotable[i].xdim*col2bypp(infotable+i);
  3010.             j=__vga_addmode(infotable[i].xdim,infotable[i].ydim,infotable[i].colors,
  3011.                         newxbytes, infotable[i].bytesperpixel);
  3012.             if(j<0)
  3013.                 {
  3014.                 puts("mach32: Out of dynamic modes for redefinition of modes with\n"
  3015.                      "        non-standard linelength. Use inhibit in case of problems.\n");
  3016.                 goto giveup;
  3017.                 }
  3018.             if(mach32_strictness==1)
  3019.                 *push(1)=CMD_MOV+i; /* later move this mode up to the newly defined.. */
  3020.             else    *push(1)=CMD_CPY+i; /* Nope, copy instead of move.. */
  3021.             *push(1)=j;        /* The destination mode. */
  3022. #ifdef 1
  3023.             printf("Redefining mode %d to %d:%dx%dx%d\n",i,j,
  3024.                     infotable[i].xdim,infotable[i].ydim,infotable[i].colors);
  3025. #endif
  3026.             }
  3027.         }
  3028.     }
  3029. giveup:
  3030. *push(1)=CMD_MSK; /* End of fixup commands */
  3031. mach32_modemixup=realloc(mach32_modemixup,mixup_ptr*sizeof(short));
  3032. if(mach32_modemixup==NULL)
  3033.     {
  3034.     puts("mach32-config: Fatal: queue shrink failed.");
  3035.     exit(-1);
  3036.     }
  3037. }
  3038.  
  3039. static char *colstr(struct info *mode)
  3040. {
  3041. static char str[4];
  3042. if(mode->colors<=256)
  3043.     {
  3044.     sprintf(str,"%d",mode->colors);
  3045.     return str;
  3046.     }
  3047. switch(mode->colors)
  3048.     {
  3049.     case 1<<15:
  3050.         return "32K";
  3051.     case 1<<16:
  3052.         return "64K";
  3053.     case 1<<24:
  3054.         if(mode->bytesperpixel==3)
  3055.             return "16M";
  3056.         if(mode->bytesperpixel==4)
  3057.             return "16M32";
  3058.     }
  3059. return "?";
  3060. }
  3061.  
  3062. static void mach32_final_modefixup(void)
  3063. {
  3064. int i;
  3065. const mode_entry *oldentry;
  3066. short *ptr,*ptm;
  3067.  
  3068.  
  3069. for(ptr=mach32_modemixup;;ptr++)
  3070.     switch(*ptr&CMD_MSK)
  3071.         {
  3072.         case CMD_MSK:    /* end marker.. */
  3073.             return;
  3074.         case CMD_DEL:    /* any mode found here is invalid. */
  3075.             mach32_modes[*ptr&~CMD_MSK]=NULL;
  3076.             break;
  3077.         case CMD_MOD:    /* skip embedded mode table */
  3078.             ptr+=SOMOD_SH;        
  3079.             break;
  3080.         case CMD_MOV:    /* move from this position to the one in next command short. */
  3081.             i=(*ptr++)&~CMD_MSK;
  3082.             mach32_modes[*ptr&~CMD_MSK]=mach32_modes[i];
  3083.             /* erase old entry... */
  3084.             mach32_modes[i]=NULL;
  3085.             break;
  3086.         case CMD_CPY:    /*Same as above, but without erase..*/
  3087.             i=(*ptr++)&~CMD_MSK;
  3088.             mach32_modes[*ptr&~CMD_MSK]=mach32_modes[i];
  3089.             break;
  3090.         case CMD_ADD:    /* Add next mode in supplied position.. */
  3091.             /*First find the mode table..*/
  3092.             ptm=ptr+1;
  3093.             while((*ptm&CMD_MSK)!=CMD_MOD)
  3094.                 ptm++;
  3095.             /* one more to skip modemarker.. */
  3096.             ptm++;
  3097.             /*Override any entry we had already for this mode..  (if the mode is acceptable)*/
  3098.             i= *ptr&~CMD_MSK;
  3099.             oldentry=mach32_modes[i];
  3100. #ifdef DEBUG
  3101.             puts("Calling mach32_modfill to add new mode.");
  3102. #endif
  3103.             mach32_modfill((mode_entry *)ptm,  col2msk(infotable+i), i );
  3104.             if(mach32_modes[i]==oldentry)
  3105.                 {
  3106.                 printf("mach32: Setting of mode %dx%dx%s failed.\n"
  3107.                     "Mode cannot be realized with your hardware\n"
  3108.                     "(or due to configured restrictions ;-) ), sorry.\n"
  3109.                     "specify verbose in config file or SVGALIB_CONFIG to get\n"
  3110.                     "detailed information\n",
  3111.                     infotable[i].xdim,infotable[i].ydim,colstr(infotable+i));
  3112.                 }
  3113.             break;
  3114.         }
  3115. }
  3116.  
  3117. static int mach32_ext_set(unsigned what, va_list params)
  3118. {
  3119. int param2, old_values;
  3120.  
  3121. switch(what)
  3122.     {
  3123.     case VGA_EXT_AVAILABLE:
  3124.         param2=va_arg(params, int);
  3125.         switch(param2)
  3126.             {
  3127.             case VGA_AVAIL_SET:
  3128.                 return VGA_EXT_AVAILABLE|VGA_EXT_SET|VGA_EXT_CLEAR|VGA_EXT_RESET;
  3129.             case VGA_AVAIL_ACCEL:
  3130.                 return 0;
  3131.             case VGA_AVAIL_FLAGS:
  3132.                 if( ((mach32_dacmode&0x7f)==DAC_MODE8) ||
  3133.                     ((mach32_dacmode&0x7f)==DAC_MODEMUX) )
  3134.                         return pos_ext_settings;
  3135.                 else    return pos_ext_settings& ~VGA_CLUT8;
  3136.             }
  3137.         return 0;
  3138.     case VGA_EXT_SET:
  3139.         old_values=ext_settings;
  3140.         ext_settings|=(va_arg(params, int))&pos_ext_settings;
  3141.         params_changed:
  3142.         if( ((old_values^ext_settings)&pos_ext_settings) &&
  3143.                 ( ((mach32_dacmode&0x7f)==DAC_MODE8) ||
  3144.                     ((mach32_dacmode&0x7f)==DAC_MODEMUX) ) )
  3145.             {
  3146.             CRITICAL=1;
  3147.             vga_lockvc();
  3148.             if(ext_settings&VGA_CLUT8)
  3149.                 outw(EXT_GE_CONF,inw(R_EXT_GE_CONF)|0x4000);
  3150.             else    outw(EXT_GE_CONF,inw(R_EXT_GE_CONF)&0xbfff);
  3151.             vga_unlockvc();
  3152.             CRITICAL=0;
  3153.             }
  3154.         return old_values;
  3155.     case VGA_EXT_CLEAR:
  3156.         old_values=ext_settings;
  3157.         ext_settings&= ~((va_arg(params, int))&pos_ext_settings);
  3158.         goto params_changed;
  3159.     case VGA_EXT_RESET:
  3160.         old_values=ext_settings;
  3161.         ext_settings=(va_arg(params, int))&pos_ext_settings;
  3162.         goto params_changed;
  3163.     default:
  3164.         return 0;
  3165.     }
  3166. }
  3167.  
  3168. static int mach32_bitblt(int srcaddr, int destaddr, int w, int h, int pitch)
  3169. {
  3170. int base,src_x,des_x,adj_w,forw_cpy;
  3171.  
  3172. #ifdef DEBUG
  3173. printf("mach32_bitblt(%xh,%xh,%d,%d,%d)\n",srcaddr,destaddr,w,h,pitch);
  3174. #endif
  3175.  
  3176. base=(forw_cpy=(srcaddr>destaddr))?destaddr:srcaddr;
  3177.  
  3178. base&= ~3;
  3179. srcaddr-=base;
  3180. destaddr-=base;
  3181.  
  3182. /*calculate resulting x values*/
  3183. src_x=srcaddr%pitch;
  3184. des_x=destaddr%pitch;
  3185.  
  3186. /*width in bytes*/
  3187. adj_w=(infotable[CM].bytesperpixel==2)?w<<1:w;
  3188.  
  3189. #ifdef DEBUG
  3190. printf("   base=%xh,src=%xh,des=%xh,src_x=%d,des_x=%d,adj_w=%d\n",base,srcaddr,
  3191.             destaddr,src_x,des_x,adj_w);
  3192. #endif
  3193.  
  3194. /*Currentsetting invalid?*/
  3195. if(((src_x+adj_w)>pitch)||((des_x+adj_w)>pitch))
  3196.     {
  3197.     int adj;
  3198.     /* try to adjust: */
  3199.     adj=des_x-src_x;
  3200.     if(adj<0)
  3201.         adj= -adj;
  3202.     adj=pitch-(adj& ~3);
  3203.     srcaddr+=adj;;
  3204.     destaddr+=adj;
  3205.     base-=adj;
  3206.     if((src_x+=adj)>=pitch)src_x-=pitch;
  3207.     if((des_x+=adj)>=pitch)des_x-=pitch;
  3208.  
  3209.     #ifdef DEBUG
  3210.     printf("   src=%xh,des=%xh,src_x=%d,des_x=%d,adj=%d\n",srcaddr,destaddr,src_x,des_x,adj);
  3211.     #endif
  3212.     /*Still invalid?*/
  3213.     if(((src_x+adj_w)>pitch)||((des_x+adj_w)>pitch))
  3214.         goto f_ugh;
  3215.     }
  3216.  
  3217. /*reduce addresses to y values:*/
  3218. srcaddr/=pitch;
  3219. destaddr/=pitch;
  3220.  
  3221. #ifdef DEBUG
  3222. printf("   >>src=%xh,des=%xh,base=%xh\n",srcaddr,destaddr,base);
  3223. #endif
  3224.  
  3225. if((srcaddr>(1535-h))||(destaddr>(1535-h)))
  3226.     goto f_ugh;
  3227. /*Reduce values to pixels*/
  3228. if(infotable[CM].bytesperpixel==2)
  3229.     {
  3230.     if((src_x&1)||(des_x&1)||(pitch&0xfffff00f))
  3231.         {
  3232.         f_ugh:
  3233.         puts("\asvgalib: mach32: mach32_bitblt can't emulate Cirrus.");
  3234.         return -1;
  3235.         }
  3236.     src_x>>=1;
  3237.     des_x>>=1;
  3238.     pitch>>=4;
  3239.     }
  3240. else    {
  3241.     if(pitch&0xfffff807)
  3242.         goto f_ugh;
  3243.     pitch>>=3;
  3244.     }
  3245.  
  3246. /*y in range is not checked. */
  3247.  
  3248. /* Do not disturb us: */
  3249. CRITICAL=1;
  3250. vga_lockvc();
  3251.  
  3252. /* Ensure std GE config to emulate simple Cirrus */
  3253. if(mach32_accelstate!=R_STANDARD)
  3254.     mach32_setstate(R_STANDARD);
  3255.  
  3256. checkqueue(5);    /* Need FIFO room for commands */
  3257.  
  3258. /* set GE base close to destination: */
  3259. outw(GE_OFFSET_LO,(unsigned short)(base>>2));
  3260. outw(GE_OFFSET_HI,(unsigned short)(base>>18));
  3261. outw(GE_PITCH,(unsigned char)pitch);
  3262. outw(DP_CONFIG,0x6011); /* Replace with VRAM blit source */
  3263. checkqueue(10);    /* Need new FIFO room for commands */
  3264. /*start coords:*/
  3265. #ifdef DEBUG
  3266. printf("   ##x=%x,y=%x,xd=%x,yd=%x\n",src_x,srcaddr,des_x,destaddr);
  3267. #endif
  3268. if(forw_cpy)
  3269.     {
  3270.     /* cpy from lower to higher addr, x, y */
  3271.     /* Use Mach32 extended blit. */
  3272.     outw(SRC_X,src_x);
  3273.     outw(SRC_X_START,src_x);
  3274.     outw(SRC_Y,srcaddr);
  3275.     outw(SRC_X_END,0x7ff&(src_x+w));
  3276.     outw(SRC_Y_DIR,1);
  3277.     outw(CUR_X,des_x);
  3278.     outw(DEST_X_START,des_x);
  3279.     outw(CUR_Y,destaddr);
  3280.     outw(DEST_X_END,0x7ff&(des_x+w));
  3281.     outw(DEST_Y_END,0x7ff&(destaddr+h));
  3282.     }
  3283. else    {
  3284.     /* rev_cpy, adj start coords. */
  3285.     /* Use Mach32 extended blit. */
  3286.     outw(SRC_X,0x7ff&(src_x+w));
  3287.     outw(SRC_X_START,0x7ff&(src_x+w));
  3288.     outw(SRC_Y,0x7ff&(srcaddr+h-1));
  3289.     outw(SRC_X_END,src_x);
  3290.     outw(SRC_Y_DIR,0);
  3291.     outw(CUR_X,0x7ff&(des_x+w));
  3292.     outw(DEST_X_START,0x7ff&(des_x+w));
  3293.     outw(CUR_Y,0x7ff&(destaddr+h-1));
  3294.     outw(DEST_X_END,des_x);
  3295.     outw(DEST_Y_END,0x7ff&(destaddr-1));
  3296.     }
  3297. /* Wait then unlock vc */
  3298. w=mach32_bltwait();    /* resets critical as well */
  3299. outw(DP_CONFIG,0x3291); /* reset to standard config.. otherwise dramatical speed down */
  3300. #ifdef DEBUG
  3301. printf("   **x=%xh,y=%xh\n",(int)inw(CUR_X),(int)inw(CUR_Y));
  3302. #endif
  3303.  
  3304. vga_unlockvc();
  3305. return w;
  3306. }
  3307.  
  3308. static int mach32_fillblt(int destaddr, int w, int h, int pitch, int c)
  3309. {
  3310. #ifdef DEBUG
  3311. printf("mach32_fillblt(%xh,%d,%d,%d,%d)\n",destaddr,w,h,pitch,c);
  3312. #endif
  3313.  
  3314. /* Do not disturb us: */
  3315. CRITICAL=1;
  3316. vga_lockvc();
  3317.  
  3318. /* Ensure std GE config to emulate simple Cirrus */
  3319. if(mach32_accelstate!=R_STANDARD)
  3320.     mach32_setstate(R_STANDARD);
  3321.  
  3322. checkqueue(5);    /* Need FIFO room for commands */
  3323. /* set GE base close to destination: */
  3324. outw(GE_OFFSET_LO,(unsigned short)(destaddr>>2));
  3325. outw(GE_OFFSET_HI,(unsigned short)(destaddr>>18));
  3326. destaddr&=3; /* remaining x offset */
  3327.  
  3328. if(infotable[CM].bytesperpixel==2)
  3329.     {
  3330.     if((destaddr&1)||(pitch&0xfffff00f))
  3331.         {
  3332.         ugh:
  3333.         puts("\asvgalib: mach32: mach32_fillblt can't emulate Cirrus.");
  3334.         CRITICAL=0;
  3335.         vga_unlockvc();
  3336.         return -1;
  3337.         }
  3338.     destaddr>>=1;
  3339.     pitch>>=4;
  3340.     }
  3341. else    {
  3342.     if(pitch&0xfffff807)
  3343.         goto ugh;
  3344.     pitch>>=3;
  3345.     }
  3346. outw(GE_PITCH,(unsigned char)pitch);
  3347. outw(FRGD_COLOR,(unsigned short)c);
  3348. outw(FRGD_MIX,0x27); /* replace with FRGD_COLOR */
  3349. checkqueue(5);    /* Need new FIFO room for commands */
  3350. /*start coords:*/
  3351. outw(CUR_X,destaddr);
  3352. outw(CUR_Y,0);
  3353. /*width+height*/
  3354. outw(MAJ_AXIS_PCNT,w-1);
  3355. outw(MULTI_FUNC_CNTL,0x7ff&(h-1));
  3356. /*kick it off*/
  3357. outw(CMD,0x50B3);    /*Rectangle fill with horz lines,pos x+y dir,draw last pel*/
  3358.  
  3359. /* Wait then unlock vc */
  3360. w=mach32_bltwait();    /* resets critical as well */
  3361. vga_unlockvc();
  3362. return w;
  3363. }
  3364.  
  3365. static int mach32_hlinelistblt(int ymin, int n, int *xmin, int *xmax, int pitch, int c)
  3366. {
  3367. #ifdef DEBUG
  3368. printf("mach32_hlinelistblt(%d,%d,%08xh,%08xh,%d,%d)\n",ymin,n,(unsigned)xmin,(unsigned)xmax,pitch,c);
  3369. #endif
  3370.  
  3371. /* Do not disturb us: */
  3372. CRITICAL=1;
  3373. vga_lockvc();
  3374.  
  3375. /* Ensure std GE config to emulate simple Cirrus */
  3376. if(mach32_accelstate!=R_STANDARD)
  3377.     mach32_setstate(R_STANDARD);
  3378.  
  3379. checkqueue(5);    /* Need FIFO room for commands */
  3380. #if 0
  3381.     /* This would be the best solution, IMHO: */
  3382.     /* set GE base equal to physical setting: */
  3383.  
  3384.     /* However.. we even dunno what is the current displaystart.. we would need access
  3385.     to a static var of vga.c for this. */
  3386.  
  3387.     outw(GE_OFFSET_LO,??);
  3388.     outw(GE_OFFSET_HI,??);
  3389. #else
  3390.     /* This is how I understand the Cirrus-code. Since we have to be compatible: */
  3391.     outw(GE_OFFSET_LO,0);
  3392.     outw(GE_OFFSET_HI,0);
  3393. #endif
  3394.  
  3395. if(infotable[CM].bytesperpixel==2)
  3396.     {
  3397.     if(pitch&0xfffff00f)
  3398.         {
  3399.         ugh:
  3400.         puts("\asvgalib: mach32: mach32_hlinelistblt can't emulate Cirrus.");
  3401.         CRITICAL=0;
  3402.         vga_unlockvc();
  3403.         return -1;
  3404.         }
  3405.     pitch>>=4;
  3406.     }
  3407. else    {
  3408.     if(pitch&0xfffff807)
  3409.         goto ugh;
  3410.     pitch>>=3;
  3411.     }
  3412. outw(GE_PITCH,(unsigned char)pitch);
  3413. outw(FRGD_COLOR,(unsigned short)c);
  3414.  
  3415. /*DP_CONFIG is replace with foreground already...*/
  3416. /*And now close your eyes and enjoy.. this is exactly what a Mach32 is built for..*/
  3417.  
  3418. checkqueue(12);    /* Need new FIFO room for commands */
  3419.  
  3420. /*I think we can trust the hardware handshake from now on. */
  3421. /*Sigh.. no we can't.. queue overruns in 16bpp */
  3422.  
  3423. while(n-- >0)
  3424.     {
  3425.     outw(CUR_X,0x7ff&(*xmin));
  3426.     outw(CUR_Y,0x7ff&(ymin++));
  3427.     if(*xmin <= *xmax)
  3428.         outw(SCAN_TO_X,(0x7ff&(*xmax+1)));
  3429.     xmin++;
  3430.     xmax++;
  3431.  
  3432.     if(!(n&3))
  3433.         checkqueue(12);
  3434.     }
  3435.  
  3436. /* Wait then unlock vc */
  3437. c=mach32_bltwait();    /* resets critical as well */
  3438. vga_unlockvc();
  3439. return c;
  3440. }
  3441.  
  3442. static void mach32_imageblt(void *srcaddr,int destaddr, int w, int h, int pitch)
  3443. {
  3444. unsigned count;    /* 16bit words needed to transfer */
  3445.  
  3446. /* Do not disturb us: */
  3447. CRITICAL=1;
  3448. vga_lockvc();
  3449.  
  3450. #ifdef DEBUG
  3451. printf("mach32_imageblt(%xh,%xh,%d,%d,%d)\n",(int)srcaddr,destaddr,w,h,pitch);
  3452. #endif
  3453.  
  3454. /* Ensure std GE config to emulate simple Cirrus */
  3455. if(mach32_accelstate!=R_STANDARD)
  3456.     mach32_setstate(R_STANDARD);
  3457.  
  3458. checkqueue(4);    /* Need FIFO room for commands */
  3459. /* set GE base close to destination: */
  3460. outw(GE_OFFSET_LO,(unsigned short)(destaddr>>2));
  3461. outw(GE_OFFSET_HI,(unsigned short)(destaddr>>18));
  3462. destaddr&=3; /* remaining x offset */
  3463.  
  3464. count=w*h;
  3465. if(infotable[CM].bytesperpixel==2)
  3466.     {
  3467.     if((destaddr&1)||(pitch&0xfffff00f))
  3468.         {
  3469.         ugh:
  3470.         puts("\asvgalib: mach32: mach32_imageblt can't emulate Cirrus.");
  3471.  
  3472.         CRITICAL=0;
  3473.         vga_unlockvc();
  3474.         return;
  3475.         }
  3476.     destaddr>>=1;
  3477.     pitch>>=4;
  3478.     }
  3479. else    {
  3480.     if(pitch&0xfffff807)
  3481.         goto ugh;
  3482.     pitch>>=3;
  3483.     count=(count+1)>>1;    /* two pixels transferred in one blow */
  3484.     }
  3485.  
  3486. if(!count)
  3487.     {
  3488.     CRITICAL=0;
  3489.     vga_unlockvc();
  3490.     return;    /* safety bailout */
  3491.     }
  3492.  
  3493. outw(GE_PITCH,(unsigned char)pitch);
  3494. outw(FRGD_MIX,0x47);    /* replace with value of PIX_TRANS */
  3495. checkqueue(6);    /* Need new FIFO room for commands, one more than actually needed to ensure
  3496.            correct hostdata fifo operation. */
  3497. /*start coords:*/
  3498. outw(CUR_X,destaddr);
  3499. outw(CUR_Y,0);
  3500. /*width+height*/
  3501. outw(MAJ_AXIS_PCNT,w-1);
  3502. outw(MULTI_FUNC_CNTL,0x7ff&(h-1));
  3503. /*kick it off*/
  3504. outw(CMD,0x53B1);    /*Rectangle fill with horz lines,pos x+y dir,draw last pel*/
  3505.             /*(set also wait for MSB in the hope that it will ensure the correct
  3506.               thing if we write out an odd number of bytes) */
  3507.  
  3508. /* Do the transfer: All handshake is done in hardware by waitstates. Note that the first
  3509.    word can be transferred w/o problems.. after that automatic handshake by waitstates is enabled
  3510.    by the ATI on it's own.
  3511.    The outs is regarding to my assembler docs not only the most simple but also by far the
  3512.    fastest way to do this. Loop unrolling will gain nothing, so it is not done.. */
  3513.  
  3514. asm("cld\n"            /* Increasing addresses.. */
  3515.     "    movw $0xe2e8,%%dx\n"    /* PIX_TRANS port */
  3516.     "    rep\n"            /* repeat.. count is in ECX */
  3517.     "    outsw\n"     :    /* Blast data out in 16bit pieces */
  3518.     /* no outputs */ :
  3519.     /* inputs */
  3520.         /* SI= source address */    "S" (srcaddr),
  3521.         /* CX= words to transfer */    "c" (count) :
  3522.     /* dx destructed: */ "%dx"
  3523.     );
  3524.  
  3525. checkqueue(2);
  3526. /*Sigh, it seems that DP_CONFIG gets affected by the 8514/A settings. so reset to standard.*/
  3527. outw(DP_CONFIG,0x3291);
  3528.  
  3529. /* The bltwait is more intended for a final checkup if everything worked ok and we
  3530. didn't lock up the Mach32 fifo */
  3531.  
  3532. /* Wait then unlock vc */
  3533. w=mach32_bltwait();    /* resets critical as well */
  3534. vga_unlockvc();
  3535. return;
  3536. }
  3537.  
  3538. static void mach32_memimageblt(void *srcaddr,int destaddr, int w, int h, int pitch)
  3539. {
  3540. char *source=srcaddr,*dest=(char * /*discard volatile*/)mach32_aperture+destaddr;
  3541.  
  3542. #ifdef DEBUG
  3543. printf("mach32_memimageblt(%xh,%xh,%d,%d,%d)\n",(int)srcaddr,destaddr,w,h,pitch);
  3544. printf("\tmemtrans: %xh -> %xh\n",(int)source,(int)dest);
  3545. #endif
  3546.  
  3547. if(!infotable[CM].bytesperpixel)
  3548.     return;
  3549.  
  3550. w*=infotable[CM].bytesperpixel;
  3551.  
  3552. if(w==pitch)
  3553.     {
  3554.     fast_memcpy(dest,source,w*h);
  3555.     }
  3556. else    {
  3557.     while(h--)
  3558.         {
  3559.         fast_memcpy(dest,source,w);
  3560.         dest+=pitch;
  3561.         source+=w;
  3562.         }
  3563.     }
  3564. #ifdef DEBUG
  3565. puts("mach32_mach32_imageblt ended.");
  3566. #endif
  3567. }
  3568.  
  3569. static int mach32_accel(unsigned operation, va_list params)
  3570. {
  3571. return -1;
  3572. }
  3573.