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