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