Rev 54 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
54 | pj | 1 | /* |
2 | Savage chipset driver |
||
3 | |||
4 | Written by Matan Ziv-Av (matan@svgalib.org) |
||
5 | |||
6 | Based on XFree 3.3.6 driver by S. Marineau and Tim Roberts. |
||
7 | And XFree 4.1.0 driver by Kevin Brosius. |
||
8 | |||
9 | */ |
||
10 | |||
11 | #include <stdlib.h> |
||
12 | //#include <stdio.h> |
||
13 | #include <string.h> |
||
14 | #include <unistd.h> |
||
15 | //#include <sys/mman.h> |
||
16 | #include "vga.h" |
||
17 | #include "libvga.h" |
||
18 | #include "driver.h" |
||
19 | #include "timing.h" |
||
20 | #include "vgaregs.h" |
||
21 | #include "interface.h" |
||
22 | #include "vgapci.h" |
||
23 | #include "endianess.h" |
||
24 | #include "vgammvgaio.h" |
||
25 | |||
26 | #define SAVAGEREG_SAVE(i) (VGA_TOTAL_REGS+i) |
||
27 | #define TOTAL_REGS (VGA_TOTAL_REGS + 64) |
||
28 | |||
29 | typedef struct { |
||
30 | |||
31 | unsigned char SR08, SR0A, SR0E, SR0F, SR10, SR11, SR12, SR13; |
||
32 | unsigned char SR15, SR18, SR1B, SR29, SR30; |
||
33 | unsigned char SR54, SR55, SR56, SR57; |
||
34 | unsigned char Clock; |
||
35 | // unsigned char s3DacRegs[0x101]; |
||
36 | unsigned char CR31, CR33, CR34, CR36, CR3A, CR3B, CR3C; |
||
37 | unsigned char CR40, CR41, CR42, CR43, CR45; |
||
38 | unsigned char CR50, CR51, CR53, CR54, CR55, CR58, CR5B, CR5D, CR5E; |
||
39 | unsigned char CR63, CR65, CR66, CR67, CR68, CR69, CR6D, CR6F; /* Video attrib. */ |
||
40 | unsigned char CR7B, CR7D; |
||
41 | unsigned char CR85, CR86, CR87, CR88; |
||
42 | unsigned char CR90, CR91, CR92, CR93, CRB0; |
||
43 | } vgaS3VRec, *vgaS3VPtr; |
||
44 | |||
45 | static int savage_init(int, int, int); |
||
46 | static void unlock(void); |
||
47 | static void lock(void); |
||
48 | static int savage_linear(int op, int param); |
||
49 | |||
50 | enum { UNKNOWN, TRIO64, TRIO3D, TRIO3D2X, |
||
51 | VIRGE, VIRGEVX, VIRGEDX, VIRGEGX2, VIRGEMX, |
||
52 | SAVAGE3D, SAVAGEMX, SAVAGE4, SAVAGEPRO, SAVAGE2000 }; |
||
53 | |||
54 | static int memory, chipset; |
||
55 | static int is_linear, linear_base; |
||
56 | |||
57 | static CardSpecs *cardspecs; |
||
58 | |||
59 | static void savage_setpage(int page) |
||
60 | { |
||
61 | __svgalib_outcrtc(0x6a, page); |
||
62 | } |
||
63 | |||
64 | static int inlinearmode(void) |
||
65 | { |
||
66 | return is_linear; |
||
67 | } |
||
68 | |||
69 | /* Fill in chipset specific mode information */ |
||
70 | |||
71 | static void savage_getmodeinfo(int mode, vga_modeinfo *modeinfo) |
||
72 | { |
||
73 | |||
74 | if(modeinfo->colors==16)return; |
||
75 | |||
76 | modeinfo->maxpixels = memory*1024/modeinfo->bytesperpixel; |
||
77 | modeinfo->maxlogicalwidth = 4088; |
||
78 | modeinfo->startaddressrange = memory * 1024 - 1; |
||
79 | modeinfo->haveblit = 0; |
||
80 | modeinfo->flags &= ~HAVE_RWPAGE; |
||
81 | |||
82 | if (modeinfo->bytesperpixel >= 1) { |
||
83 | if(linear_base)modeinfo->flags |= CAPABLE_LINEAR; |
||
84 | if (inlinearmode()) |
||
85 | modeinfo->flags |= IS_LINEAR | LINEAR_MODE; |
||
86 | } |
||
87 | } |
||
88 | |||
89 | /* Read and save chipset-specific registers */ |
||
90 | |||
91 | static int savage_saveregs(unsigned char regs[]) |
||
92 | { |
||
93 | unsigned char cr3a, cr66; |
||
94 | vgaS3VPtr save = (vgaS3VPtr)(regs+VGA_TOTAL_REGS); |
||
95 | |||
96 | unlock(); |
||
97 | |||
98 | cr66 = __svgalib_incrtc(0x66); |
||
99 | __svgalib_outcrtc(0x66, cr66 | 0x80); |
||
100 | cr3a = __svgalib_incrtc(0x3a); |
||
101 | __svgalib_outcrtc(0x3a, cr3a | 0x80); |
||
102 | |||
103 | cr66 = __svgalib_incrtc(0x66); |
||
104 | __svgalib_outcrtc(0x66, cr66 | 0x80); |
||
105 | cr3a = __svgalib_incrtc(0x3a); |
||
106 | __svgalib_outcrtc(0x3a, cr3a | 0x80); |
||
107 | |||
108 | #if 0 |
||
109 | save = (vgaS3VPtr)vgaHWSave((vgaHWPtr)save, sizeof(vgaS3VRec)); |
||
110 | #endif |
||
111 | |||
112 | __svgalib_outcrtc(0x66, cr66); |
||
113 | __svgalib_outcrtc(0x3a, cr3a); |
||
114 | __svgalib_outcrtc(0x66, cr66); |
||
115 | __svgalib_outcrtc(0x3a, cr3a); |
||
116 | |||
117 | /* First unlock extended sequencer regs */ |
||
118 | save->SR08 = __svgalib_inseq(0x08); |
||
119 | __svgalib_outseq(0x08, 0x06); |
||
120 | |||
121 | /* Now we save all the s3 extended regs we need */ |
||
122 | save->CR31 = __svgalib_incrtc(0x31); |
||
123 | save->CR34 = __svgalib_incrtc(0x34); |
||
124 | save->CR36 = __svgalib_incrtc(0x36); |
||
125 | save->CR3A = __svgalib_incrtc(0x3a); |
||
126 | |||
127 | if(chipset>TRIO3D) |
||
128 | save->CR40 = __svgalib_incrtc(0x40); |
||
129 | |||
130 | if(chipset==VIRGEMX) |
||
131 | save->CR41 = __svgalib_incrtc(0x41); |
||
132 | |||
133 | save->CR42 = __svgalib_incrtc(0x42); |
||
134 | save->CR45 = __svgalib_incrtc(0x45); |
||
135 | |||
136 | if(chipset>=SAVAGE3D) |
||
137 | save->CR50 = __svgalib_incrtc(0x50); |
||
138 | |||
139 | save->CR51 = __svgalib_incrtc(0x51); |
||
140 | save->CR53 = __svgalib_incrtc(0x53); |
||
141 | |||
142 | if(chipset<SAVAGE3D){ |
||
143 | save->CR54 = __svgalib_incrtc(0x54); |
||
144 | save->CR55 = __svgalib_incrtc(0x55); |
||
145 | } |
||
146 | |||
147 | save->CR58 = __svgalib_incrtc(0x58); |
||
148 | |||
149 | if(chipset<SAVAGE3D) |
||
150 | save->CR63 = __svgalib_incrtc(0x63); |
||
151 | |||
152 | save->CR66 = __svgalib_incrtc(0x66); |
||
153 | save->CR67 = __svgalib_incrtc(0x67); |
||
154 | save->CR68 = __svgalib_incrtc(0x68); |
||
155 | save->CR69 = __svgalib_incrtc(0x69); |
||
156 | |||
157 | if(chipset>=SAVAGE3D) |
||
158 | save->CR6F = __svgalib_incrtc(0x6f); |
||
159 | |||
160 | save->CR33 = __svgalib_incrtc(0x33); |
||
161 | |||
162 | if((chipset==TRIO3D2X)||(chipset==VIRGEGX2)||(chipset==VIRGEMX)) |
||
163 | save->CR85 = __svgalib_incrtc(0x85); |
||
164 | |||
165 | if((chipset==VIRGEDX)||(chipset>=SAVAGE3D)) |
||
166 | save->CR86 = __svgalib_incrtc(0x86); |
||
167 | |||
168 | if((chipset==TRIO3D2X)||(chipset==VIRGEGX2)||(chipset==VIRGEMX)) { |
||
169 | save->CR7B = __svgalib_incrtc(0x7b); |
||
170 | save->CR7D = __svgalib_incrtc(0x7d); |
||
171 | save->CR87 = __svgalib_incrtc(0x87); |
||
172 | save->CR92 = __svgalib_incrtc(0x92); |
||
173 | save->CR93 = __svgalib_incrtc(0x93); |
||
174 | } |
||
175 | |||
176 | if((chipset==TRIO3D2X)||(chipset==VIRGEDX)||(chipset==VIRGEGX2)|| |
||
177 | (chipset==VIRGEMX)) { |
||
178 | save->CR90 = __svgalib_incrtc(0x90); |
||
179 | save->CR91 = __svgalib_incrtc(0x91); |
||
180 | } |
||
181 | |||
182 | if(chipset>=SAVAGE3D) { |
||
183 | save->CR88 = __svgalib_incrtc(0x88); |
||
184 | save->CR90 = __svgalib_incrtc(0x90); |
||
185 | save->CR91 = __svgalib_incrtc(0x91); |
||
186 | save->CRB0 = __svgalib_incrtc(0xb0) | 0x80; |
||
187 | } |
||
188 | |||
189 | save->CR3B = __svgalib_incrtc(0x3b); |
||
190 | save->CR3C = __svgalib_incrtc(0x3c); |
||
191 | save->CR43 = __svgalib_incrtc(0x43); |
||
192 | save->CR5D = __svgalib_incrtc(0x5d); |
||
193 | save->CR5E = __svgalib_incrtc(0x5e); |
||
194 | save->CR65 = __svgalib_incrtc(0x65); |
||
195 | |||
196 | if(chipset<SAVAGE3D) |
||
197 | save->CR6D = __svgalib_incrtc(0x6d); |
||
198 | |||
199 | /* Save sequencer extended regs for DCLK PLL programming */ |
||
200 | save->SR0E = __svgalib_inseq(0x0E); |
||
201 | save->SR10 = __svgalib_inseq(0x10); |
||
202 | save->SR11 = __svgalib_inseq(0x11); |
||
203 | save->SR12 = __svgalib_inseq(0x12); |
||
204 | save->SR13 = __svgalib_inseq(0x13); |
||
205 | |||
206 | if(chipset>=SAVAGE3D) |
||
207 | save->SR29 = __svgalib_inseq(0x29); |
||
208 | |||
209 | if((chipset==TRIO3D2X)||(chipset==VIRGEGX2)||(chipset==VIRGEMX)) { |
||
210 | save->SR29 = __svgalib_inseq(0x29); |
||
211 | save->SR54 = __svgalib_inseq(0x54); |
||
212 | save->SR55 = __svgalib_inseq(0x55); |
||
213 | save->SR56 = __svgalib_inseq(0x56); |
||
214 | save->SR57 = __svgalib_inseq(0x57); |
||
215 | } |
||
216 | |||
217 | save->SR15 = __svgalib_inseq(0x15); |
||
218 | |||
219 | if(chipset>=SAVAGE3D) |
||
220 | save->SR30 = __svgalib_inseq(0x30); |
||
221 | |||
222 | save->SR18 = __svgalib_inseq(0x18); |
||
223 | |||
224 | if(chipset>=SAVAGE3D) |
||
225 | save->SR1B = __svgalib_inseq(0x1B); |
||
226 | |||
227 | if(chipset<=TRIO3D) { |
||
228 | save->SR0A = __svgalib_inseq(0x0a); |
||
229 | save->SR0F = __svgalib_inseq(0x0f); |
||
230 | } |
||
231 | |||
232 | __svgalib_outcrtc(0x3a, cr3a); |
||
233 | __svgalib_outcrtc(0x66, cr66); |
||
234 | |||
235 | return TOTAL_REGS - VGA_TOTAL_REGS; |
||
236 | } |
||
237 | |||
238 | /* Set chipset-specific registers */ |
||
239 | |||
240 | static void savage_setregs(const unsigned char regs[], int mode) |
||
241 | { |
||
242 | int tmp; |
||
243 | vgaS3VPtr restore = (vgaS3VPtr)(regs+VGA_TOTAL_REGS); |
||
244 | |||
245 | unlock(); |
||
246 | |||
247 | #if 0 |
||
248 | /* Are we going to reenable STREAMS in this new mode? */ |
||
249 | s3vPriv.STREAMSRunning = restore->CR67 & 0x0c; |
||
250 | |||
251 | /* First reset GE to make sure nothing is going on */ |
||
252 | outb(vgaCRIndex, 0x66); |
||
253 | if(port_in(vgaCRReg) & 0x01) S3SAVGEReset(0,__LINE__,__FILE__); |
||
254 | #endif |
||
255 | |||
256 | /* As per databook, always disable STREAMS before changing modes */ |
||
257 | __svgalib_outcrtc(0x67, __svgalib_incrtc(0x67)&0xf3); |
||
258 | |||
259 | if(chipset<SAVAGE3D) |
||
260 | __svgalib_outcrtc(0x63, restore->CR63); |
||
261 | |||
262 | __svgalib_outcrtc(0x66, restore->CR66); |
||
263 | __svgalib_outcrtc(0x3a, restore->CR3A); |
||
264 | __svgalib_outcrtc(0x31, restore->CR31); |
||
265 | __svgalib_outcrtc(0x58, restore->CR58); |
||
266 | |||
267 | if(chipset<SAVAGE3D) |
||
268 | __svgalib_outcrtc(0x55, restore->CR55); |
||
269 | |||
270 | #if 0 /* why is it done twice? */ |
||
271 | __svgalib_outseq(0x08, 0x06); |
||
272 | __svgalib_outseq(0x12, restore->SR12); |
||
273 | __svgalib_outseq(0x13, restore->SR13); |
||
274 | __svgalib_outseq(0x29, restore->SR29); |
||
275 | __svgalib_outseq(0x15, restore->SR15); |
||
276 | #endif |
||
277 | |||
278 | __svgalib_outcrtc(0x53, restore->CR53); |
||
279 | __svgalib_outcrtc(0x5d, restore->CR5D); |
||
280 | __svgalib_outcrtc(0x5e, restore->CR5E); |
||
281 | __svgalib_outcrtc(0x3b, restore->CR3B); |
||
282 | __svgalib_outcrtc(0x3c, restore->CR3C); |
||
283 | __svgalib_outcrtc(0x43, restore->CR43); |
||
284 | __svgalib_outcrtc(0x65, restore->CR65); |
||
285 | |||
286 | if(chipset<SAVAGE3D) |
||
287 | __svgalib_outcrtc(0x6d, restore->CR6D); |
||
288 | |||
289 | /* Restore the desired video mode with CR67 */ |
||
290 | |||
291 | if(chipset<SAVAGE3D) |
||
292 | __svgalib_outcrtc(0x67, 0x50 | (__svgalib_incrtc(0x67)&0x0f)); |
||
293 | else |
||
294 | __svgalib_outcrtc(0x67, 0x50 | (__svgalib_incrtc(0x67)&0xf3)); |
||
295 | |||
296 | sleep(1); |
||
297 | __svgalib_outcrtc(0x67, restore->CR67&0xf3); |
||
298 | |||
299 | __svgalib_outcrtc(0x34, restore->CR34); |
||
300 | |||
301 | if(chipset>TRIO3D) |
||
302 | __svgalib_outcrtc(0x40, restore->CR40); |
||
303 | |||
304 | if(chipset==VIRGEMX) |
||
305 | __svgalib_outcrtc(0x41, restore->CR41); |
||
306 | |||
307 | __svgalib_outcrtc(0x42, restore->CR42); |
||
308 | __svgalib_outcrtc(0x45, restore->CR45); |
||
309 | |||
310 | if(chipset>=SAVAGE3D) |
||
311 | __svgalib_outcrtc(0x50, restore->CR50); |
||
312 | |||
313 | __svgalib_outcrtc(0x51, restore->CR51); |
||
314 | |||
315 | if(chipset<SAVAGE3D) |
||
316 | __svgalib_outcrtc(0x54, restore->CR54); |
||
317 | |||
318 | __svgalib_outcrtc(0x36, restore->CR36); |
||
319 | __svgalib_outcrtc(0x68, restore->CR68); |
||
320 | __svgalib_outcrtc(0x69, restore->CR69); |
||
321 | |||
322 | if(chipset>=SAVAGE3D) |
||
323 | __svgalib_outcrtc(0x6f, restore->CR6F); |
||
324 | |||
325 | __svgalib_outcrtc(0x33, restore->CR33); |
||
326 | |||
327 | if(chipset>=SAVAGE3D) { |
||
328 | __svgalib_outcrtc(0x86, restore->CR86); |
||
329 | __svgalib_outcrtc(0x88, restore->CR88); |
||
330 | __svgalib_outcrtc(0x90, restore->CR90); |
||
331 | __svgalib_outcrtc(0x91, restore->CR91); |
||
332 | __svgalib_outcrtc(0xb0, restore->CRB0); |
||
333 | } |
||
334 | |||
335 | if((chipset==TRIO3D2X)||(chipset==VIRGEGX2)||(chipset==VIRGEMX)) |
||
336 | __svgalib_outcrtc(0x85, restore->CR85); |
||
337 | |||
338 | if(chipset==VIRGEDX) |
||
339 | __svgalib_outcrtc(0x86, restore->CR86); |
||
340 | |||
341 | if(chipset==VIRGEGX2) { |
||
342 | __svgalib_outcrtc(0x7b, restore->CR7B); |
||
343 | __svgalib_outcrtc(0x7d, restore->CR7D); |
||
344 | __svgalib_outcrtc(0x87, restore->CR87); |
||
345 | __svgalib_outcrtc(0x92, restore->CR92); |
||
346 | __svgalib_outcrtc(0x93, restore->CR93); |
||
347 | } |
||
348 | |||
349 | if((chipset==TRIO3D2X)||(chipset==VIRGEDX)||(chipset==VIRGEGX2)||(chipset==VIRGEMX)) { |
||
350 | __svgalib_outcrtc(0x90, restore->CR90); |
||
351 | __svgalib_outcrtc(0x91, restore->CR91); |
||
352 | } |
||
353 | |||
354 | __svgalib_outseq(0x08, 0x06); |
||
355 | /* Restore extended sequencer regs for MCLK. SR10 == 255 indicates that |
||
356 | * we should leave the default SR10 and SR11 values there. |
||
357 | */ |
||
358 | |||
359 | if (restore->SR10 != 255) { |
||
360 | __svgalib_outseq(0x10, restore->SR10); |
||
361 | __svgalib_outseq(0x11, restore->SR11); |
||
362 | } |
||
363 | |||
364 | /* Restore extended sequencer regs for DCLK */ |
||
365 | |||
366 | __svgalib_outseq(0x12, restore->SR12); |
||
367 | __svgalib_outseq(0x13, restore->SR13); |
||
368 | |||
369 | if(chipset>=SAVAGE3D) |
||
370 | __svgalib_outseq(0x29, restore->SR29); |
||
371 | |||
372 | if((chipset==TRIO3D2X)||(chipset==VIRGEGX2)||(chipset==VIRGEMX)) { |
||
373 | __svgalib_outseq(0x29, restore->SR29); |
||
374 | __svgalib_outseq(0x54, restore->SR54); |
||
375 | __svgalib_outseq(0x55, restore->SR55); |
||
376 | __svgalib_outseq(0x56, restore->SR56); |
||
377 | __svgalib_outseq(0x57, restore->SR57); |
||
378 | } |
||
379 | |||
380 | __svgalib_outseq(0x18, restore->SR18); |
||
381 | |||
382 | if(chipset>=SAVAGE3D) |
||
383 | __svgalib_outseq(0x1B, restore->SR1B); |
||
384 | |||
385 | tmp = __svgalib_inseq(0x15) & ~0x21; |
||
386 | __svgalib_outseq(0x15, tmp | 0x03); |
||
387 | __svgalib_outseq(0x15, tmp | 0x23); |
||
388 | __svgalib_outseq(0x15, tmp | 0x03); |
||
389 | __svgalib_outseq(0x15, restore->SR15); |
||
390 | |||
391 | sleep(1); |
||
392 | |||
393 | if(chipset<=TRIO3D) { |
||
394 | __svgalib_outseq(0x0a, restore->SR0A); |
||
395 | __svgalib_outseq(0x0f, restore->SR0F); |
||
396 | } else if (chipset >= SAVAGE3D) { |
||
397 | __svgalib_outseq(0x30, restore->SR30); |
||
398 | } |
||
399 | |||
400 | __svgalib_outseq(0x08, restore->SR08); |
||
401 | |||
402 | |||
403 | /* Now write out CR67 in full, possibly starting STREAMS */ |
||
404 | |||
405 | __svgalib_outcrtc(0x67, 0x50); |
||
406 | sleep(1); |
||
407 | __svgalib_outcrtc(0x67, restore->CR67&0xf3); |
||
408 | |||
409 | __svgalib_outcrtc(0x53, restore->CR53); |
||
410 | __svgalib_outcrtc(0x66, restore->CR66); |
||
411 | __svgalib_outcrtc(0x3a, restore->CR3A); |
||
412 | } |
||
413 | |||
414 | |||
415 | /* Return nonzero if mode is available */ |
||
416 | |||
417 | static int savage_modeavailable(int mode) |
||
418 | { |
||
419 | struct info *info; |
||
420 | ModeTiming *modetiming; |
||
421 | ModeInfo *modeinfo; |
||
422 | |||
423 | if (IS_IN_STANDARD_VGA_DRIVER(mode)) |
||
424 | return __svgalib_vga_driverspecs.modeavailable(mode); |
||
425 | |||
426 | info = &__svgalib_infotable[mode]; |
||
427 | |||
428 | if (memory * 1024 < info->ydim * info->xbytes) |
||
429 | return 0; |
||
430 | |||
431 | modeinfo = __svgalib_createModeInfoStructureForSvgalibMode(mode); |
||
432 | |||
433 | if(modeinfo->bytesPerPixel==3) return 0; |
||
434 | |||
435 | modetiming = malloc(sizeof(ModeTiming)); |
||
436 | |||
437 | if (__svgalib_getmodetiming(modetiming, modeinfo, cardspecs)) { |
||
438 | free(modetiming); |
||
439 | free(modeinfo); |
||
440 | return 0; |
||
441 | } |
||
442 | |||
443 | free(modetiming); |
||
444 | free(modeinfo); |
||
445 | return SVGADRV; |
||
446 | } |
||
447 | |||
448 | /* Local, called by setmode(). */ |
||
449 | #define BASE_FREQ 14.31818 |
||
450 | |||
451 | static void savageCalcClock(long freq, int min_m, int min_n1, int max_n1, int min_n2, int max_n2, |
||
452 | long freq_min, long freq_max, unsigned int *mdiv, unsigned int *ndiv, unsigned int *r) |
||
453 | { |
||
454 | double ffreq, ffreq_min, ffreq_max; |
||
455 | double div, diff, best_diff; |
||
456 | unsigned int m; |
||
457 | unsigned char n1, n2; |
||
458 | unsigned char best_n1=16+2, best_n2=2, best_m=125+2; |
||
459 | |||
460 | ffreq = freq / 1000.0 / BASE_FREQ; |
||
461 | ffreq_min = freq_min / 1000.0 / BASE_FREQ; |
||
462 | ffreq_max = freq_max / 1000.0 / BASE_FREQ; |
||
463 | |||
464 | if (ffreq < ffreq_min / (1<<max_n2)) { |
||
465 | ffreq = ffreq_min / (1<<max_n2); |
||
466 | } |
||
467 | if (ffreq > ffreq_max / (1<<min_n2)) { |
||
468 | ffreq = ffreq_max / (1<<min_n2); |
||
469 | } |
||
470 | |||
471 | /* work out suitable timings */ |
||
472 | |||
473 | best_diff = ffreq; |
||
474 | |||
475 | for (n2=min_n2; n2<=max_n2; n2++) { |
||
476 | for (n1 = min_n1+2; n1 <= max_n1+2; n1++) { |
||
477 | m = (int)(ffreq * n1 * (1<<n2) + 0.5) ; |
||
478 | if (m < min_m+2 || m > 127+2) |
||
479 | continue; |
||
480 | div = (double)(m) / (double)(n1); |
||
481 | if ((div >= ffreq_min) && |
||
482 | (div <= ffreq_max)) { |
||
483 | diff = ffreq - div / (1<<n2); |
||
484 | if (diff < 0.0) |
||
485 | diff = -diff; |
||
486 | if (diff < best_diff) { |
||
487 | best_diff = diff; |
||
488 | best_m = m; |
||
489 | best_n1 = n1; |
||
490 | best_n2 = n2; |
||
491 | } |
||
492 | } |
||
493 | } |
||
494 | } |
||
495 | |||
496 | *ndiv = best_n1 - 2; |
||
497 | *r = best_n2; |
||
498 | *mdiv = best_m - 2; |
||
499 | } |
||
500 | |||
501 | |||
502 | static void savage_initializemode(unsigned char *moderegs, |
||
503 | ModeTiming * modetiming, ModeInfo * modeinfo, int mode) |
||
85 | giacomo | 504 | { |
505 | #ifdef NL |
||
506 | #undef NL |
||
507 | #endif |
||
54 | pj | 508 | #define NL (1<<30) |
509 | int i, j, dclk, width, tmp; |
||
510 | int clocklimits[14][2]={ |
||
511 | {}, |
||
512 | {86000,0}, /* Trio 64 - Guess */ |
||
513 | {115000,115000}, /* Trio 3D */ |
||
514 | {NL,0}, /* Trio 3D2X */ |
||
515 | {80000,0}, /* Virge */ |
||
516 | {110000,110000}, /* Virge VX */ |
||
517 | {80000,0}, /* Virge DX */ |
||
518 | {NL,0}, /* Virge GX2 */ |
||
519 | {NL,0}, /* Virge MX */ |
||
520 | {NL,NL}, /* Savage 3D */ |
||
521 | {0,0}, /* Savage MX */ |
||
522 | {NL,NL}, /* Savage 4 */ |
||
523 | {NL,NL}, /* Savage Pro */ |
||
524 | {230000,230000}, /* Savage 2000 */ |
||
525 | }; |
||
526 | int cargs[14][4]= { |
||
527 | {}, |
||
528 | {31, 0, 3, 86000}, /* Trio 64 - Guess */ |
||
529 | {31, 0, 4, 230000}, |
||
530 | {31, 0, 4, 170000}, |
||
531 | {31, 0, 3, 135000}, |
||
532 | {31, 0, 4, 220000}, |
||
533 | {31, 0, 3, 135000}, |
||
534 | {31, 0, 4, 170000}, |
||
535 | {31, 0, 4, 170000}, |
||
536 | {127, 0, 4, 180000}, |
||
537 | {127, 0, 4, 180000}, |
||
538 | {127, 0, 4, 180000}, |
||
539 | {127, 0, 4, 180000}, |
||
540 | {127, 0, 4, 180000}, |
||
541 | }; |
||
542 | #undef NL |
||
543 | |||
544 | vgaS3VPtr new = (vgaS3VPtr)(moderegs+VGA_TOTAL_REGS); |
||
545 | |||
546 | if(modeinfo->bitsPerPixel==16) { |
||
547 | if((chipset==VIRGE)|| (chipset==TRIO64)) { |
||
548 | modetiming->HDisplay *=2; |
||
549 | modetiming->HSyncStart *=2; |
||
550 | modetiming->HSyncEnd *=2; |
||
551 | modetiming->HTotal *=2; |
||
552 | modetiming->CrtcHDisplay =modetiming->HDisplay; |
||
553 | modetiming->CrtcHSyncStart =modetiming->HSyncStart; |
||
554 | modetiming->CrtcHSyncEnd =modetiming->HSyncEnd; |
||
555 | modetiming->CrtcHTotal =modetiming->HTotal; |
||
556 | } |
||
557 | } |
||
558 | |||
559 | __svgalib_setup_VGA_registers(moderegs, modetiming, modeinfo); |
||
560 | |||
561 | tmp = __svgalib_incrtc(0x3a); |
||
562 | if((chipset==TRIO3D2X)||(chipset==VIRGEGX2)||(chipset==VIRGEMX)) { |
||
563 | if(0) new->CR3A = tmp | 0x90; /* ENH 256, no PCI burst! */ |
||
564 | else new->CR3A = (tmp & 0x38) | 0x10; /* ENH 256, PCI burst */ |
||
565 | } else { |
||
566 | if(0) new->CR3A = tmp | 0x95; /* ENH 256, no PCI burst! */ |
||
567 | else new->CR3A = (tmp & 0x7f) | 0x15; /* ENH 256, PCI burst */ |
||
568 | } |
||
569 | |||
570 | new->CR53 |= 0x08; /* Disables MMIO */ |
||
571 | new->CR31 = 0x09; /* Enable 64k window */ |
||
572 | |||
573 | if(chipset==VIRGEVX) { |
||
574 | new->CR66 = 0x90; |
||
575 | new->CR63 = 0x09; |
||
576 | new->CR58 = 0x40; |
||
577 | } else { |
||
578 | if((chipset==TRIO3D2X)||(chipset==VIRGEGX2)||(chipset==VIRGEMX)) { |
||
579 | new->CR63 = 0x08; |
||
580 | } else { |
||
581 | new->CR63 = 0x00; |
||
582 | } |
||
583 | new->CR66 = 0x89; |
||
584 | new->CR58 = 0; |
||
585 | } |
||
586 | |||
587 | /* Now do clock PLL programming. Use the s3gendac function to get m,n */ |
||
588 | /* Also determine if we need doubling etc. */ |
||
589 | |||
590 | dclk = modetiming->pixelClock; |
||
591 | new->CR67 = 0x00; /* Defaults */ |
||
592 | if(chipset > TRIO3D) { |
||
593 | new->SR15 = 0x03 | 0x80; |
||
594 | if(chipset==VIRGE) |
||
595 | new->SR15 = (__svgalib_inseq(0x15) & 0x80) | 3; |
||
596 | } else { |
||
597 | new->SR15 = (__svgalib_inseq(0x15) & 0x80) | 3; |
||
598 | new->SR0A = __svgalib_inseq(0x0a); |
||
599 | } |
||
600 | new->SR18 = 0x00; |
||
601 | new->CR43 = 0x00; |
||
602 | new->CR45 = 0x00; |
||
603 | new->CR65 = 0x00; |
||
604 | new->CR54 = 0x00; |
||
605 | |||
606 | if(chipset > TRIO3D) |
||
607 | new->CR40 = __svgalib_incrtc(0x40) & 0xfe ; |
||
608 | |||
609 | new->SR10 = 255; /* This is a reserved value, so we use as flag */ |
||
610 | new->SR11 = 255; |
||
611 | |||
612 | new->SR1B = 0; |
||
613 | new->SR30 = __svgalib_inseq(0x30); |
||
614 | |||
615 | switch( modeinfo->colorBits ) { |
||
616 | case 8: |
||
617 | new->CR67 = 0x00; /* 8bpp, 1 pixel/clock */ |
||
618 | if(dclk >= clocklimits[chipset][0]) new->CR67 |= 0x10; |
||
619 | break; |
||
620 | case 15: |
||
621 | new->CR67 = 0x20; |
||
622 | if(dclk >= clocklimits[chipset][1]) new->CR67 |= 0x10; |
||
623 | break; |
||
624 | case 16: |
||
625 | new->CR67 = 0x40; |
||
626 | if(dclk >= clocklimits[chipset][1]) new->CR67 |= 0x10; |
||
627 | break; |
||
628 | case 24: |
||
629 | new->CR67 = 0xd0; |
||
630 | break; |
||
631 | } |
||
632 | |||
633 | /* Now the special cases */ |
||
634 | if(chipset==VIRGE) { |
||
635 | if(new->CR67 == 0x10) { |
||
636 | new->SR15 |= 0x10; |
||
637 | new->SR18 = 0x80; |
||
638 | } |
||
639 | } |
||
640 | |||
641 | { |
||
642 | unsigned int m, n, r; |
||
643 | |||
644 | savageCalcClock(dclk, 1, 1, cargs[chipset][0], cargs[chipset][1], |
||
645 | cargs[chipset][2], cargs[chipset][3], cargs[chipset][3]*2, |
||
646 | &m, &n, &r); |
||
647 | if(chipset < SAVAGE3D) |
||
648 | new->SR12 = (r << 5) | (n & 0x1F); |
||
649 | else new->SR12 = (r << 6) | (n & 0x3F); |
||
650 | new->SR13 = m & 0xFF; |
||
651 | new->SR29 = (r & 4) | (m & 0x100) >> 5 | (n & 0x40) >> 2; |
||
652 | } |
||
653 | |||
654 | |||
655 | /* If we have an interlace mode, set the interlace bit. Note that mode |
||
656 | * vertical timings are already adjusted by the standard VGA code |
||
657 | */ |
||
658 | if (modetiming->flags & INTERLACED) { |
||
659 | new->CR42 = 0x20; /* Set interlace mode */ |
||
660 | } else { |
||
661 | new->CR42 = 0x00; |
||
662 | } |
||
663 | |||
664 | /* Set display fifo */ |
||
665 | if((chipset==TRIO3D2X)||(chipset==VIRGEGX2)||(chipset==VIRGEMX)) { |
||
666 | new->CR34 = 0; |
||
667 | } else { |
||
668 | new->CR34 = 0x10; |
||
669 | } |
||
670 | |||
671 | /* Now we adjust registers for extended mode timings */ |
||
672 | /* This is taken without change from the accel/s3_virge code */ |
||
673 | |||
674 | i = ((((modetiming->CrtcHTotal >> 3) - 5) & 0x100) >> 8) | |
||
675 | ((((modetiming->CrtcHDisplay >> 3) - 1) & 0x100) >> 7) | |
||
676 | ((((modetiming->CrtcHSyncStart >> 3) - 1) & 0x100) >> 6) | |
||
677 | ((modetiming->CrtcHSyncStart & 0x800) >> 7); |
||
678 | |||
679 | if ((modetiming->CrtcHSyncEnd >> 3) - (modetiming->CrtcHSyncStart >> 3) > 64) |
||
680 | i |= 0x08; /* add another 64 DCLKs to blank pulse width */ |
||
681 | |||
682 | if ((modetiming->CrtcHSyncEnd >> 3) - (modetiming->CrtcHSyncStart >> 3) > 32) |
||
683 | i |= 0x20; /* add another 32 DCLKs to hsync pulse width */ |
||
684 | |||
685 | j = ( moderegs[0] + ((i&0x01)<<8) |
||
686 | + moderegs[4] + ((i&0x10)<<4) + 1) / 2; |
||
687 | |||
688 | if (j-(moderegs[4] + ((i&0x10)<<4)) < 4) { |
||
689 | if (moderegs[4] + ((i&0x10)<<4) + 4 <= moderegs[0]+ ((i&0x01)<<8)) |
||
690 | j = moderegs[4] + ((i&0x10)<<4) + 4; |
||
691 | else |
||
692 | j = moderegs[0]+ ((i&0x01)<<8) + 1; |
||
693 | } |
||
694 | |||
695 | new->CR3B = j & 0xFF; |
||
696 | i |= (j & 0x100) >> 2; |
||
697 | new->CR3C = (moderegs[0] + ((i&0x01)<<8))/2; |
||
698 | |||
699 | new->CR5D = i; |
||
700 | |||
701 | new->CR5E = (((modetiming->CrtcVTotal - 2) & 0x400) >> 10) | |
||
702 | (((modetiming->CrtcVDisplay - 1) & 0x400) >> 9) | |
||
703 | (((modetiming->CrtcVSyncStart) & 0x400) >> 8) | |
||
704 | (((modetiming->CrtcVSyncStart) & 0x400) >> 6) | 0x40; |
||
705 | |||
706 | width = modeinfo->lineWidth >> 3; |
||
707 | moderegs[19] = 0xFF & width; |
||
708 | new->CR51 = (0x300 & width) >> 4; /* Extension bits */ |
||
709 | |||
710 | /* And finally, select clock source 2 for programmable PLL */ |
||
711 | moderegs[VGA_MISCOUTPUT] |= 0x0c; |
||
712 | |||
713 | if(chipset>=SAVAGE3D) { |
||
714 | /* Set frame buffer description */ |
||
715 | if (modeinfo->colorBits <= 8) { |
||
716 | new->CR50 = 0; |
||
717 | } else { |
||
718 | if (modeinfo->colorBits <= 16) { |
||
719 | new->CR50 = 0x10; |
||
720 | } else { |
||
721 | new->CR50 = 0x30; |
||
722 | } |
||
723 | } |
||
724 | |||
725 | if (modeinfo->width == 640) |
||
726 | new->CR50 |= 0x40; |
||
727 | else if (modeinfo->width == 800) |
||
728 | new->CR50 |= 0x80; |
||
729 | else if (modeinfo->width == 1024); |
||
730 | else if (modeinfo->width == 1152) |
||
731 | new->CR50 |= 0x01; |
||
732 | else if (modeinfo->width == 1280) |
||
733 | new->CR50 |= 0x41; |
||
734 | else if (modeinfo->width == 2048 && new->CR31 & 2); |
||
735 | else if (modeinfo->width == 1600) |
||
736 | new->CR50 |= 0x81; /* TODO: need to consider bpp=4 */ |
||
737 | else |
||
738 | new->CR50 |= 0xC1; /* default to use GlobalBD */ |
||
739 | |||
740 | new->CR33 = 0x08; |
||
741 | new->CR6F = __svgalib_incrtc(0x6f); |
||
742 | new->CR86 = __svgalib_incrtc(0x86); |
||
743 | new->CR88 = __svgalib_incrtc(0x88); |
||
744 | new->CRB0 = __svgalib_incrtc(0xb0) | 0x80; |
||
745 | } else /* trio, virge */ { |
||
746 | new->CR33 = 0x20; |
||
747 | if((chipset==VIRGEDX)||(chipset<=TRIO3D)) { |
||
748 | new->CR86 = 0x80; |
||
749 | } |
||
750 | |||
751 | if((chipset!=VIRGEVX)&&(chipset!=VIRGE)) { |
||
752 | new->CR91 = (modeinfo->lineWidth+7) >> 3; |
||
753 | new->CR90 = 0x80 | ((modeinfo->lineWidth+7) >> 11); |
||
754 | } |
||
755 | |||
756 | if(chipset == VIRGEVX) { |
||
757 | if(modeinfo->colorBits>16) new->CR6D = 0x51 ; else new->CR6D=0; |
||
758 | } else { |
||
759 | new->CR6D = __svgalib_incrtc(0x6d); |
||
760 | new->CR65 &= ~0x38; |
||
761 | switch(modeinfo->colorBits) { |
||
762 | case 8: |
||
763 | break; |
||
764 | case 15: |
||
765 | case 16: |
||
766 | new->CR65 |= 2<<3; |
||
767 | break; |
||
768 | default: |
||
769 | new->CR65 |= 4<<3; |
||
770 | break; |
||
771 | } |
||
772 | } |
||
773 | |||
774 | if(chipset == VIRGEMX) { |
||
775 | new->SR54=0x10; |
||
776 | new->SR55=0x80; |
||
777 | new->SR56=0x10; |
||
778 | new->SR57=0x80; |
||
779 | } else { |
||
780 | new->SR54=0x1f; |
||
781 | new->SR55=0x9f; |
||
782 | new->SR56=0x1f; |
||
783 | new->SR57=0x9f; |
||
784 | } |
||
785 | } |
||
786 | |||
787 | /* Now we handle various XConfig memory options and others */ |
||
788 | |||
789 | new->CR36 = __svgalib_incrtc(0x36); |
||
790 | |||
791 | #if 0 |
||
792 | if (mode->Private) { |
||
793 | new->CR67 &= ~1; |
||
794 | if( |
||
795 | (s3vPriv.chip != S3_SAVAGE2000) && |
||
796 | (mode->Private[0] & (1 << S3_INVERT_VCLK)) && |
||
797 | (mode->Private[S3_INVERT_VCLK]) |
||
798 | ) |
||
799 | new->CR67 |= 1; |
||
800 | |||
801 | if (mode->Private[0] & (1 << S3_BLANK_DELAY)) { |
||
802 | new->CR65 = (new->CR65 & ~0x38) |
||
803 | | (mode->Private[S3_BLANK_DELAY] & 0x07) << 3; |
||
804 | } |
||
805 | } |
||
806 | #endif |
||
807 | |||
808 | if(__svgalib_emulatepage || is_linear) new->CR58 |= 0x13; |
||
809 | new->CR68 = __svgalib_incrtc(0x68); |
||
810 | new->CR69 = 0; |
||
811 | |||
812 | return ; |
||
813 | } |
||
814 | |||
815 | |||
816 | static int savage_setmode(int mode, int prv_mode) |
||
817 | { |
||
818 | unsigned char *moderegs; |
||
819 | ModeTiming *modetiming; |
||
820 | ModeInfo *modeinfo; |
||
821 | |||
822 | if (IS_IN_STANDARD_VGA_DRIVER(mode)) { |
||
823 | __svgalib_outcrtc(0x34, 0); |
||
824 | return __svgalib_vga_driverspecs.setmode(mode, prv_mode); |
||
825 | } |
||
826 | if (!savage_modeavailable(mode)) |
||
827 | return 1; |
||
828 | |||
829 | modeinfo = __svgalib_createModeInfoStructureForSvgalibMode(mode); |
||
830 | |||
831 | modetiming = malloc(sizeof(ModeTiming)); |
||
832 | if (__svgalib_getmodetiming(modetiming, modeinfo, cardspecs)) { |
||
833 | free(modetiming); |
||
834 | free(modeinfo); |
||
835 | return 1; |
||
836 | } |
||
837 | |||
838 | moderegs = malloc(TOTAL_REGS); |
||
839 | |||
840 | savage_initializemode(moderegs, modetiming, modeinfo, mode); |
||
841 | free(modetiming); |
||
842 | |||
843 | __svgalib_setregs(moderegs); /* Set standard regs. */ |
||
844 | savage_setregs(moderegs, mode); /* Set extended regs. */ |
||
845 | free(moderegs); |
||
846 | |||
847 | free(modeinfo); |
||
848 | |||
849 | return 0; |
||
850 | } |
||
851 | |||
852 | |||
853 | /* Unlock chipset-specific registers */ |
||
854 | |||
855 | static void unlock(void) |
||
856 | { |
||
857 | __svgalib_outcrtc(0x11,__svgalib_incrtc(0x11)&0x7f); |
||
858 | __svgalib_outcrtc(0x38, 0x48); |
||
859 | __svgalib_outcrtc(0x39, 0xa5); |
||
860 | __svgalib_outcrtc(0x40,__svgalib_incrtc(0x40)&0xfe); |
||
861 | } |
||
862 | |||
863 | static void lock(void) |
||
864 | { |
||
865 | } |
||
866 | |||
867 | |||
868 | #define VENDOR_ID 0x5333 |
||
869 | |||
870 | /* Indentify chipset, initialize and return non-zero if detected */ |
||
871 | |||
872 | int savage_test(void) |
||
873 | { |
||
874 | int found; |
||
875 | int id; |
||
876 | unsigned long buf[64]; |
||
877 | |||
878 | found=__svgalib_pci_find_vendor_vga(VENDOR_ID,buf,0); |
||
879 | id=(buf[0]>>16)&0xffff; |
||
880 | if(found)return 0; |
||
881 | switch(id) { |
||
882 | case 0x8811: |
||
883 | case 0x8903: |
||
884 | case 0x8904: |
||
885 | case 0x8a13: |
||
886 | case 0x5631: |
||
887 | case 0x883d: |
||
888 | case 0x8a01: |
||
889 | case 0x8a10: |
||
890 | case 0x8c00: |
||
891 | case 0x8c01: |
||
892 | case 0x8c02: |
||
893 | case 0x8c03: |
||
894 | case 0x8a20: |
||
895 | case 0x8a21: |
||
896 | case 0x8a22: |
||
897 | case 0x8a23: |
||
898 | case 0x8c10: |
||
899 | case 0x8c12: |
||
900 | case 0x9102: |
||
901 | case 0x8d03: |
||
902 | case 0x8d04: |
||
903 | savage_init(0,0,0); |
||
904 | return 1; |
||
905 | break; |
||
906 | default: |
||
907 | return 0; |
||
908 | } |
||
909 | } |
||
910 | |||
911 | |||
912 | /* Set display start address (not for 16 color modes) */ |
||
913 | |||
914 | static void savage_setdisplaystart(int address) |
||
915 | { |
||
916 | address=address >> 2; |
||
917 | __svgalib_outcrtc(0x0d,address&0xff); |
||
918 | __svgalib_outcrtc(0x0c,(address>>8)&0xff); |
||
919 | __svgalib_outcrtc(0x69,(address>>16)&0xff); |
||
920 | |||
921 | } |
||
922 | |||
923 | /* Set logical scanline length (usually multiple of 8) */ |
||
924 | /* Cirrus supports multiples of 8, up to 4088 */ |
||
925 | |||
926 | static void savage_setlogicalwidth(int width) |
||
927 | { |
||
928 | int offset = width >> 3; |
||
929 | |||
930 | __svgalib_outcrtc(0x13,offset&0xff); |
||
931 | } |
||
932 | |||
933 | static int savage_linear(int op, int param) |
||
934 | { |
||
935 | if (op==LINEAR_ENABLE){ |
||
936 | __svgalib_outcrtc(0x58,__svgalib_incrtc(0x58)|0x13); |
||
937 | is_linear=1; |
||
938 | return 0; |
||
939 | }; |
||
940 | if (op==LINEAR_DISABLE) { |
||
941 | __svgalib_outcrtc(0x58,__svgalib_incrtc(0x58)&~0x13); |
||
942 | is_linear=0; |
||
943 | return 0; |
||
944 | }; |
||
945 | if (op==LINEAR_QUERY_BASE) return linear_base; |
||
946 | if (op == LINEAR_QUERY_RANGE || op == LINEAR_QUERY_GRANULARITY) return 0; /* No granularity or range. */ |
||
947 | else return -1; /* Unknown function. */ |
||
948 | } |
||
949 | |||
950 | static int match_programmable_clock(int clock) |
||
951 | { |
||
952 | return clock ; |
||
953 | } |
||
954 | |||
955 | static int map_clock(int bpp, int clock) |
||
956 | { |
||
957 | return clock ; |
||
958 | } |
||
959 | |||
960 | static int map_horizontal_crtc(int bpp, int pixelclock, int htiming) |
||
961 | { |
||
962 | return htiming; |
||
963 | } |
||
964 | |||
965 | static struct { |
||
966 | unsigned char c8; |
||
967 | unsigned short c15; |
||
968 | unsigned short c16; |
||
969 | unsigned int c32; |
||
970 | } cursor_colors[16*2]; |
||
971 | |||
972 | static int pal=1, palette[768]; |
||
973 | |||
974 | static int findcolor(int rgb) { |
||
975 | int i,j,k,l=0; |
||
976 | |||
977 | if(pal)vga_getpalvec(0,256,palette); |
||
978 | pal=0; |
||
979 | k=0xffffff; |
||
980 | for(i=0;i<256;i++) { |
||
981 | j=((rgb&0xff)-(palette[i*3+2]<<2))*((rgb&0xff)-(palette[i*3+2]<<2))+ |
||
982 | (((rgb>>8)&0xff)-(palette[i*3+1]<<2))*(((rgb>>8)&0xff)-(palette[i*3+1]<<2))+ |
||
983 | (((rgb>>16)&0xff)-(palette[i*3]<<2))*(((rgb>>16)&0xff)-(palette[i*3]<<2)); |
||
984 | if(j==0) { |
||
985 | return i; |
||
986 | } |
||
987 | if(j<k) { |
||
988 | k=j; |
||
989 | l=i; |
||
990 | } |
||
991 | } |
||
992 | return l; |
||
993 | } |
||
994 | |||
995 | static int savage_cursor( int cmd, int p1, int p2, int p3, int p4, void *p5) { |
||
996 | unsigned long *b3; |
||
997 | unsigned char *buf; |
||
998 | int i, j; |
||
999 | unsigned int l1, l2; |
||
1000 | |||
1001 | switch(cmd){ |
||
1002 | case CURSOR_INIT: |
||
1003 | return 1; |
||
1004 | case CURSOR_HIDE: |
||
1005 | __svgalib_outcrtc(0x45,__svgalib_incrtc(0x45)&0xfe); |
||
1006 | break; |
||
1007 | case CURSOR_SHOW: |
||
1008 | __svgalib_outcrtc(0x45,__svgalib_incrtc(0x45)|0x01); /* Windows */ |
||
1009 | break; |
||
1010 | case CURSOR_POSITION: |
||
1011 | __svgalib_outcrtc(0x46,p1>>8); |
||
1012 | __svgalib_outcrtc(0x47,p1&0xff); |
||
1013 | __svgalib_outcrtc(0x49,p2&0xff); |
||
1014 | __svgalib_outcrtc(0x4e,0); |
||
1015 | __svgalib_outcrtc(0x4f,0); |
||
1016 | __svgalib_outcrtc(0x48,p2>>8); |
||
1017 | break; |
||
1018 | case CURSOR_SELECT: |
||
1019 | i=memory-(16-p1); |
||
1020 | switch(CI.colors) { |
||
1021 | case 256: |
||
1022 | __svgalib_incrtc(0x45); |
||
1023 | __svgalib_outcrtc(0x4b,cursor_colors[p1*2].c8); |
||
1024 | __svgalib_outcrtc(0x4b,cursor_colors[p1*2].c8); |
||
1025 | __svgalib_incrtc(0x45); |
||
1026 | __svgalib_outcrtc(0x4a,cursor_colors[p1*2+1].c8); |
||
1027 | __svgalib_outcrtc(0x4a,cursor_colors[p1*2+1].c8); |
||
1028 | break; |
||
1029 | case 32768: |
||
1030 | __svgalib_incrtc(0x45); |
||
1031 | __svgalib_outcrtc(0x4b,cursor_colors[p1*2].c15&0xff); |
||
1032 | __svgalib_outcrtc(0x4b,cursor_colors[p1*2].c15>>8); |
||
1033 | __svgalib_outcrtc(0x4b,cursor_colors[p1*2].c15&0xff); |
||
1034 | __svgalib_outcrtc(0x4b,cursor_colors[p1*2].c15>>8); |
||
1035 | __svgalib_incrtc(0x45); |
||
1036 | __svgalib_outcrtc(0x4a,cursor_colors[p1*2+1].c15&0xff); |
||
1037 | __svgalib_outcrtc(0x4a,cursor_colors[p1*2+1].c15>>8); |
||
1038 | __svgalib_outcrtc(0x4a,cursor_colors[p1*2+1].c15&0xff); |
||
1039 | __svgalib_outcrtc(0x4a,cursor_colors[p1*2+1].c15>>8); |
||
1040 | break; |
||
1041 | case 65536: |
||
1042 | __svgalib_incrtc(0x45); |
||
1043 | __svgalib_outcrtc(0x4b,cursor_colors[p1*2].c16&0xff); |
||
1044 | __svgalib_outcrtc(0x4b,cursor_colors[p1*2].c16>>8); |
||
1045 | __svgalib_outcrtc(0x4b,cursor_colors[p1*2].c16&0xff); |
||
1046 | __svgalib_outcrtc(0x4b,cursor_colors[p1*2].c16>>8); |
||
1047 | __svgalib_incrtc(0x45); |
||
1048 | __svgalib_outcrtc(0x4a,cursor_colors[p1*2+1].c16&0xff); |
||
1049 | __svgalib_outcrtc(0x4a,cursor_colors[p1*2+1].c16>>8); |
||
1050 | __svgalib_outcrtc(0x4a,cursor_colors[p1*2+1].c16&0xff); |
||
1051 | __svgalib_outcrtc(0x4a,cursor_colors[p1*2+1].c16>>8); |
||
1052 | break; |
||
1053 | case (1<<24): |
||
1054 | __svgalib_incrtc(0x45); |
||
1055 | __svgalib_outcrtc(0x4b,cursor_colors[p1*2].c32&0xff); |
||
1056 | __svgalib_outcrtc(0x4b,(cursor_colors[p1*2].c32>>8)&0xff); |
||
1057 | __svgalib_outcrtc(0x4b,(cursor_colors[p1*2].c32>>16)&0xff); |
||
1058 | __svgalib_incrtc(0x45); |
||
1059 | __svgalib_outcrtc(0x4a,cursor_colors[p1*2+1].c32&0xff); |
||
1060 | __svgalib_outcrtc(0x4a,(cursor_colors[p1*2+1].c32>>8)&0xff); |
||
1061 | __svgalib_outcrtc(0x4a,(cursor_colors[p1*2+1].c32>>16)&0xff); |
||
1062 | break; |
||
1063 | } |
||
1064 | __svgalib_outcrtc(0x4d, i&0xff); |
||
1065 | __svgalib_outcrtc(0x4c, i>>8); |
||
1066 | break; |
||
1067 | case CURSOR_IMAGE: |
||
1068 | buf=malloc(1024); |
||
1069 | cursor_colors[p1*2].c8=findcolor(p3); |
||
1070 | cursor_colors[p1*2].c32=p3; |
||
1071 | cursor_colors[p1*2].c16=((p3&0xf80000)>>8)|((p3&0xfc00)>>5)|((p3&0xf8)>>3); |
||
1072 | cursor_colors[p1*2].c15=((p3&0xf80000)>>9)|((p3&0xf800)>>5)|((p3&0xf8)>>3); |
||
1073 | cursor_colors[p1*2+1].c8=findcolor(p4); |
||
1074 | cursor_colors[p1*2+1].c32=p4; |
||
1075 | cursor_colors[p1*2+1].c16=((p4&0xf80000)>>8)|((p4&0xfc00)>>5)|((p4&0xf8)>>3); |
||
1076 | cursor_colors[p1*2+1].c15=((p4&0xf80000)>>9)|((p4&0xf800)>>5)|((p4&0xf8)>>3); |
||
1077 | i=memory*1024-(16-p1)*1024; |
||
1078 | b3=(unsigned long *)p5; |
||
1079 | switch(p2) { |
||
1080 | case 0: |
||
1081 | for(j=0;j<32;j++) { |
||
1082 | l2=*(b3+j); |
||
1083 | l1=*(b3+32+j); |
||
1084 | l1=BE32(l1); |
||
1085 | l2=BE32(l2); |
||
1086 | l2=l2&l1; |
||
1087 | l1=~l1; |
||
1088 | *(unsigned short *)(buf+16*j)=l1&0xffff; |
||
1089 | *(unsigned short *)(buf+16*j+2)=l2&0xffff; |
||
1090 | *(unsigned short *)(buf+16*j+4)=(l1>>16)&0xffff; |
||
1091 | *(unsigned short *)(buf+16*j+6)=(l2>>16)&0xffff; |
||
1092 | *(unsigned short *)(buf+16*j+8)=0xffff; |
||
1093 | *(unsigned short *)(buf+16*j+10)=0; |
||
1094 | *(unsigned short *)(buf+16*j+12)=0xffff; |
||
1095 | *(unsigned short *)(buf+16*j+14)=0; |
||
1096 | } |
||
1097 | for(j=32;j<64;j++) { |
||
1098 | *(unsigned short *)(buf+16*j)=0xffff; |
||
1099 | *(unsigned short *)(buf+16*j+2)=0; |
||
1100 | *(unsigned short *)(buf+16*j+4)=0xffff; |
||
1101 | *(unsigned short *)(buf+16*j+6)=0; |
||
1102 | *(unsigned short *)(buf+16*j+8)=0xffff; |
||
1103 | *(unsigned short *)(buf+16*j+10)=0; |
||
1104 | *(unsigned short *)(buf+16*j+12)=0xffff; |
||
1105 | *(unsigned short *)(buf+16*j+14)=0; |
||
1106 | } |
||
1107 | break; |
||
1108 | } |
||
1109 | vga_drawscansegment(buf, i/CI.bytesperpixel,0,1024); |
||
1110 | break; |
||
1111 | } |
||
1112 | return 0; |
||
1113 | } |
||
1114 | |||
1115 | /* Function table (exported) */ |
||
1116 | DriverSpecs __svgalib_savage_driverspecs = |
||
1117 | { |
||
1118 | savage_saveregs, |
||
1119 | savage_setregs, |
||
1120 | unlock, |
||
1121 | lock, |
||
1122 | savage_test, |
||
1123 | savage_init, |
||
1124 | savage_setpage, |
||
1125 | NULL, |
||
1126 | NULL, |
||
1127 | savage_setmode, |
||
1128 | savage_modeavailable, |
||
1129 | savage_setdisplaystart, |
||
1130 | savage_setlogicalwidth, |
||
1131 | savage_getmodeinfo, |
||
1132 | 0, /* old blit funcs */ |
||
1133 | 0, |
||
1134 | 0, |
||
1135 | 0, |
||
1136 | 0, |
||
1137 | 0, /* ext_set */ |
||
1138 | 0, /* accel */ |
||
1139 | savage_linear, |
||
1140 | 0, /* accelspecs, filled in during init. */ |
||
1141 | NULL, /* Emulation */ |
||
1142 | savage_cursor, |
||
1143 | }; |
||
1144 | |||
1145 | /* Initialize chipset (called after detection) */ |
||
1146 | static int savage_init(int force, int par1, int par2) |
||
1147 | { |
||
1148 | unsigned long buf[64]; |
||
1149 | unsigned long mmio_base; |
||
1150 | int found=0, config1; |
||
1151 | int mems[8]={2,4,8,12,16,32,64,2}; |
||
1152 | char *chipnames[] = {"Unknown", "Trio64", "Trio 3D", "Trio 3d/2X", "Virge", "Virge VX", |
||
1153 | "Virge DX", "Virge GX2", "Virge MX", |
||
1154 | "Savage3D", "SavageMX", "Savage4", "SavagePro", "Savage2000"}; |
||
1155 | int vmems[9][8]= { {0}, |
||
1156 | {0,0,0,1,0,0,1,0}, |
||
1157 | {4,0,4,0,2,0,0,0}, |
||
1158 | {4,0,4,0,0,0,2,0}, |
||
1159 | {4,0,0,0,2,0,1,0}, |
||
1160 | {2,4,6,8,2,4,6,8}, |
||
1161 | {4,0,0,0,2,0,1,0}, |
||
1162 | {0,0,4,4,0,0,2,2}, |
||
1163 | {0,0,4,4,0,0,2,2} |
||
1164 | }; |
||
1165 | int id; |
||
1166 | |||
1167 | // unlock(); |
||
1168 | if (force) { |
||
1169 | memory = par1; |
||
1170 | chipset = par2; |
||
1171 | } else { |
||
1172 | |||
1173 | }; |
||
1174 | |||
1175 | found=__svgalib_pci_find_vendor_vga(VENDOR_ID,buf,0); |
||
1176 | if (found) { |
||
1177 | printk("Savage Card Not Found !\n"); |
||
1178 | return 0; |
||
1179 | } |
||
1180 | |||
1181 | id=(buf[0]>>16)&0xffff; |
||
1182 | switch(id) { |
||
1183 | case 0x8811: |
||
1184 | chipset = TRIO64; |
||
1185 | break; |
||
1186 | case 0x8903: |
||
1187 | case 0x8904: |
||
1188 | chipset = TRIO3D; |
||
1189 | break; |
||
1190 | case 0x8a13: |
||
1191 | chipset = TRIO3D2X; |
||
1192 | break; |
||
1193 | case 0x5631: |
||
1194 | chipset = VIRGE; |
||
1195 | break; |
||
1196 | case 0x883d: |
||
1197 | chipset = VIRGEVX; |
||
1198 | break; |
||
1199 | case 0x8a01: |
||
1200 | chipset = VIRGEDX; |
||
1201 | break; |
||
1202 | case 0x8a10: |
||
1203 | chipset = VIRGEGX2; |
||
1204 | break; |
||
1205 | case 0x8c00: |
||
1206 | case 0x8c01: |
||
1207 | case 0x8c02: |
||
1208 | case 0x8c03: |
||
1209 | chipset = VIRGEMX; |
||
1210 | break; |
||
1211 | case 0x8a20: |
||
1212 | case 0x8a21: |
||
1213 | chipset = SAVAGE3D; |
||
1214 | break; |
||
1215 | case 0x8c10: |
||
1216 | case 0x8c12: |
||
1217 | chipset = SAVAGEMX; |
||
1218 | break; |
||
1219 | case 0x8a22: |
||
1220 | case 0x8a23: |
||
1221 | case 0x8d03: |
||
1222 | case 0x8d04: |
||
1223 | chipset = SAVAGE4; |
||
1224 | break; |
||
1225 | case 0x9102: |
||
1226 | chipset = SAVAGE2000; |
||
1227 | break; |
||
1228 | default: |
||
1229 | chipset = UNKNOWN; |
||
1230 | } |
||
1231 | |||
1232 | if(chipset<SAVAGE3D) { |
||
1233 | linear_base=buf[4]&0xffffff00; |
||
1234 | mmio_base = linear_base + 0x1000000; |
||
1235 | #if 1 /* You need to write linear address to CR59 5A, and enable MMIO in CR53 - |
||
1236 | But how to do it if it's a secondary card??? */ |
||
1237 | if(__svgalib_secondary) { |
||
1238 | __svgalib_mmio_base = mmio_base; |
||
1239 | __svgalib_mmio_size = 0x10000; |
||
1240 | map_mmio(); |
||
1241 | __svgalib_vgammbase=0x8000; |
||
1242 | __svgalib_mm_io_mapio(); |
||
1243 | } |
||
1244 | #endif |
||
1245 | unlock(); |
||
1246 | config1=__svgalib_incrtc(0x36); |
||
1247 | memory = 1024 * vmems[chipset][(config1&0xe0)>>5]; |
||
1248 | } else { |
||
1249 | linear_base=buf[5]&0xffffff00; |
||
1250 | mmio_base =buf[4]&0xffffff00; |
||
1251 | __svgalib_mmio_base = mmio_base; |
||
1252 | __svgalib_mmio_size = 0x10000; |
||
1253 | map_mmio(); |
||
1254 | |||
1255 | __svgalib_vgammbase=0x8000; |
||
1256 | __svgalib_mm_io_mapio(); |
||
1257 | unlock(); |
||
1258 | |||
1259 | config1=__svgalib_incrtc(0x36); |
||
1260 | if(chipset >= SAVAGE4) { |
||
1261 | memory=mems[config1>>5]*1024; |
||
1262 | } else { |
||
1263 | switch(config1>>6) { |
||
1264 | case 0: |
||
1265 | memory=8192; |
||
1266 | break; |
||
1267 | case 0x40: |
||
1268 | case 0x80: |
||
1269 | memory=4096; |
||
1270 | break; |
||
1271 | case 0xC0: |
||
1272 | memory=2048; |
||
1273 | break; |
||
1274 | } |
||
1275 | } |
||
1276 | } |
||
1277 | |||
1278 | if (__svgalib_driver_report) { |
||
1279 | printk(KERN_INFO "Using SAVAGE driver, %iKB. Chipset: %s\n",memory, chipnames[chipset]); |
||
1280 | }; |
||
1281 | cardspecs = malloc(sizeof(CardSpecs)); |
||
1282 | cardspecs->videoMemory = memory; |
||
1283 | cardspecs->maxPixelClock4bpp = 0; |
||
1284 | cardspecs->maxPixelClock8bpp = 250000; |
||
1285 | cardspecs->maxPixelClock16bpp = 250000; |
||
1286 | cardspecs->maxPixelClock24bpp = 220000; |
||
1287 | cardspecs->maxPixelClock32bpp = 220000; |
||
1288 | cardspecs->flags = INTERLACE_DIVIDE_VERT | CLOCK_PROGRAMMABLE; |
||
1289 | cardspecs->maxHorizontalCrtc = 4088; |
||
1290 | cardspecs->nClocks = 0; |
||
1291 | cardspecs->mapClock = map_clock; |
||
1292 | cardspecs->mapHorizontalCrtc = map_horizontal_crtc; |
||
1293 | cardspecs->matchProgrammableClock=match_programmable_clock; |
||
1294 | __svgalib_driverspecs = &__svgalib_savage_driverspecs; |
||
1295 | __svgalib_banked_mem_base=0xa0000; |
||
1296 | __svgalib_banked_mem_size=0x10000; |
||
1297 | __svgalib_linear_mem_base=linear_base; |
||
1298 | __svgalib_linear_mem_size=memory*0x400; |
||
1299 | |||
1300 | sleep(4); |
||
1301 | |||
1302 | return 0; |
||
1303 | |||
1304 | } |