~ubuntu-branches/ubuntu/gutsy/vnc4/gutsy

« back to all changes in this revision

Viewing changes to unix/xc/programs/Xserver/hw/xfree86/drivers/s3/s3_Ti.c

  • Committer: Bazaar Package Importer
  • Author(s): Ola Lundqvist
  • Date: 2006-05-15 20:35:17 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20060515203517-l4lre1ku942mn26k
Tags: 4.1.1+X4.3.0-10
* Correction of critical security issue. Thanks to Martin Kogler
  <e9925248@student.tuwien.ac.at> that informed me about the issue,
  and provided the patch.
  This flaw was originally found by Steve Wiseman of intelliadmin.com.
* Applied patch from Javier Kohen <jkohen@users.sourceforge.net> that
  inform the user that only 8 first characters of the password will
  actually be used when typing more than 8 characters, closes:
  #355619.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *      Copyright 2001  Ani Joshi <ajoshi@unixbox.com>
 
3
 * 
 
4
 *      XFree86 4.x driver for S3 chipsets
 
5
 * 
 
6
 * 
 
7
 * Permission to use, copy, modify, distribute, and sell this software and its
 
8
 * documentation for any purpose is hereby granted without fee, provided that
 
9
 * the above copyright notice appear in all copies and that both that copyright
 
10
 * notice and this permission notice appear in supporting documentation and
 
11
 * that the name of Ani Joshi not be used in advertising or
 
12
 * publicity pertaining to distribution of the software without specific,
 
13
 * written prior permission.  Ani Joshi makes no representations
 
14
 * about the suitability of this software for any purpose.  It is provided
 
15
 * "as-is" without express or implied warranty.
 
16
 *                 
 
17
 * ANI JOSHI DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 
18
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
 
19
 * EVENT SHALL ANI JOSHI BE LIABLE FOR ANY SPECIAL, INDIRECT OR
 
20
 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
 
21
 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
 
22
 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 
23
 * PERFORMANCE OF THIS SOFTWARE.
 
24
 *
 
25
 *
 
26
 */
 
27
/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/s3/s3_Ti.c,v 1.5 2003/02/17 16:45:24 dawes Exp $ */
 
28
 
 
29
#include "xf86.h"
 
30
#include "xf86_OSproc.h"
 
31
#include "xf86_ansic.h"
 
32
 
 
33
#include "compiler.h"
 
34
 
 
35
#include "TI.h"
 
36
 
 
37
#include "s3.h"
 
38
 
 
39
 
 
40
#define TI_WRITE_ADDR           0x3C8   /* CR55 low bit == 0 */
 
41
#define TI_RAMDAC_DATA          0x3C9   /* CR55 low bit == 0 */
 
42
#define TI_PIXEL_MASK           0x3C6   /* CR55 low bit == 0 */
 
43
#define TI_READ_ADDR            0x3C7   /* CR55 low bit == 0 */
 
44
#define TI_INDEX_REG            0x3C6   /* CR55 low bit == 1 */
 
45
#define TI_DATA_REG             0x3C7   /* CR55 low bit == 1 */
 
46
 
 
47
#define TIDAC_output_clock_select       0x1b
 
48
#define TIDAC_auxiliary_ctrl            0x29
 
49
#define TIDAC_general_io_ctrl           0x2a
 
50
#define TIDAC_general_io_data           0x2b
 
51
#define TIDAC_cursor_color_0_red        0x23
 
52
#define TIDAC_cursor_color_0_green      0x24
 
53
#define TIDAC_cursor_color_0_blue       0x25
 
54
#define TIDAC_cursor_color_1_red        0x26
 
55
#define TIDAC_cursor_color_1_green      0x27
 
56
#define TIDAC_cursor_color_1_blue       0x28
 
57
#define TIDAC_cursor_x_low              0x00
 
58
#define TIDAC_cursor_x_high             0x01
 
59
#define TIDAC_cursor_y_low              0x02
 
60
#define TIDAC_cursor_y_high             0x03
 
61
#define TIDAC_cursor_ram_addr_low       0x08
 
62
#define TIDAC_cursor_ram_addr_high      0x09
 
63
#define TIDAC_cursor_ram_data           0x0a
 
64
 
 
65
 
 
66
#define TI_REF_FREQ             14.31818  /* 3025 only */
 
67
 
 
68
#undef  FREQ_MIN
 
69
#define FREQ_MIN   12000
 
70
#define FREQ_MAX  220000
 
71
 
 
72
 
 
73
 
 
74
void S3OutTiIndReg(ScrnInfoPtr pScrn, CARD32 reg, unsigned char mask,
 
75
                   unsigned char data)
 
76
{
 
77
        S3Ptr pS3 = S3PTR(pScrn);
 
78
        int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg;
 
79
        unsigned char tmp, tmp1, tmp2 = 0x00;
 
80
 
 
81
        outb(vgaCRIndex, 0x55);
 
82
        tmp = inb(vgaCRReg) & 0xfc;
 
83
        outb(vgaCRReg, tmp | 0x01);
 
84
        tmp1 = inb(TI_INDEX_REG);
 
85
        outb(TI_INDEX_REG, reg);
 
86
 
 
87
        if (mask != 0x00)
 
88
                tmp2 = inb(TI_DATA_REG) & mask;
 
89
        outb(TI_DATA_REG, tmp2 | data);
 
90
 
 
91
        outb(TI_INDEX_REG, tmp1);
 
92
        outb(vgaCRReg, tmp);
 
93
}
 
94
 
 
95
 
 
96
static unsigned char S3InTiIndReg(ScrnInfoPtr pScrn, CARD32 reg)
 
97
{
 
98
        S3Ptr pS3 = S3PTR(pScrn);
 
99
        int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg;
 
100
        unsigned char tmp, tmp1, ret;
 
101
 
 
102
        outb(vgaCRIndex, 0x55);
 
103
        tmp = inb(vgaCRReg) & 0xfc;
 
104
        outb(vgaCRReg, tmp | 0x01);
 
105
        tmp1 = inb(TI_INDEX_REG);
 
106
        outb(TI_INDEX_REG, reg);
 
107
 
 
108
        ret = inb(TI_DATA_REG);
 
109
 
 
110
        outb(TI_INDEX_REG, tmp1);
 
111
        outb(vgaCRReg, tmp);
 
112
 
 
113
        return ret;
 
114
}
 
115
 
 
116
 
 
117
Bool S3TiDACProbe(ScrnInfoPtr pScrn)
 
118
{
 
119
        S3Ptr pS3 = S3PTR(pScrn);
 
120
        int found = 0;
 
121
        int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg;
 
122
        unsigned char cr55, cr45, cr43, cr5c;
 
123
        unsigned char TIndx, TIndx2, TIdata;
 
124
 
 
125
        if (!S3_964_SERIES())
 
126
                return FALSE;
 
127
 
 
128
        outb(vgaCRIndex, 0x43);
 
129
        cr43 = inb(vgaCRReg);
 
130
        outb(vgaCRReg, cr43 & ~0x02);
 
131
 
 
132
        outb(vgaCRIndex, 0x45);
 
133
        cr45 = inb(vgaCRReg);
 
134
 
 
135
        outb(vgaCRIndex, 0x55);
 
136
        cr55 = inb(vgaCRReg);
 
137
        outb(vgaCRReg, (cr55 & 0xfc) | 0x01);
 
138
 
 
139
        TIndx = inb(TI_INDEX_REG);
 
140
        outb(TI_INDEX_REG, TIDAC_id);
 
141
        if(inb(TI_DATA_REG) == 0x20) {
 
142
                found = TI3020_RAMDAC;
 
143
                cr43 &= ~0x02;
 
144
                cr45 &= ~0x20;
 
145
        } else {
 
146
                outb(vgaCRIndex, 0x5c);
 
147
                cr5c = inb(vgaCRReg);
 
148
                outb(vgaCRReg, cr5c & 0xdf);
 
149
                TIndx2 = inb(TI_INDEX_REG);
 
150
                outb(TI_INDEX_REG, TIDAC_ind_curs_ctrl);
 
151
                TIdata = inb(TI_DATA_REG);
 
152
                outb(TI_DATA_REG, TIdata & 0x7f);
 
153
 
 
154
                outb(TI_INDEX_REG, TIDAC_id);
 
155
                if (inb(TI_DATA_REG) == 0x25) {
 
156
                        found = TI3025_RAMDAC;
 
157
                        cr43 &= ~0x02;
 
158
                        cr45 &= ~0x20;
 
159
                }
 
160
 
 
161
                outb(TI_INDEX_REG, TIDAC_ind_curs_ctrl);
 
162
                outb(TI_DATA_REG, TIdata);
 
163
                outb(TI_INDEX_REG, TIndx2);
 
164
                outb(vgaCRIndex, 0x5c);
 
165
                outb(vgaCRReg, cr5c);
 
166
        }
 
167
 
 
168
        outb(TI_INDEX_REG, TIndx);
 
169
        outb(vgaCRIndex, 0x55);
 
170
        outb(vgaCRReg, cr55);
 
171
 
 
172
        outb(vgaCRIndex, 0x45);
 
173
        outb(vgaCRReg, cr45);
 
174
 
 
175
        outb(vgaCRIndex, 0x43);
 
176
        outb(vgaCRReg, cr43);
 
177
 
 
178
        if (found) {
 
179
                RamDacInit(pScrn, pS3->RamDacRec);
 
180
                pS3->RamDac = RamDacHelperCreateInfoRec();
 
181
                pS3->RamDac->RamDacType = found;
 
182
                return TRUE;
 
183
        }
 
184
 
 
185
        return FALSE;
 
186
}
 
187
 
 
188
 
 
189
void S3TiDAC_Save(ScrnInfoPtr pScrn)
 
190
{
 
191
        S3Ptr pS3 = S3PTR(pScrn);
 
192
        S3RegPtr save = &pS3->SavedRegs;
 
193
        int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg;
 
194
 
 
195
        if (pS3->RamDac->RamDacType == TI3025_RAMDAC) {
 
196
                unsigned char cr5c;
 
197
 
 
198
                outb(vgaCRIndex, 0x5c);
 
199
                cr5c = inb(vgaCRReg);
 
200
                outb(vgaCRReg, cr5c & 0xdf);
 
201
 
 
202
                save->dacregs[TIDAC_ind_curs_ctrl] =
 
203
                                 S3InTiIndReg(pScrn, TIDAC_ind_curs_ctrl);
 
204
                S3OutTiIndReg(pScrn, TIDAC_ind_curs_ctrl, 0x7f, 0x00);
 
205
        }
 
206
 
 
207
        save->dacregs[TIDAC_true_color_ctrl] = 
 
208
                        S3InTiIndReg(pScrn, TIDAC_true_color_ctrl);
 
209
        save->dacregs[TIDAC_multiplex_ctrl] =
 
210
                        S3InTiIndReg(pScrn, TIDAC_multiplex_ctrl);
 
211
        save->dacregs[TIDAC_clock_select] =
 
212
                        S3InTiIndReg(pScrn, TIDAC_clock_select);
 
213
        save->dacregs[TIDAC_output_clock_select] =
 
214
                        S3InTiIndReg(pScrn, TIDAC_output_clock_select);
 
215
        save->dacregs[TIDAC_general_ctrl] =
 
216
                        S3InTiIndReg(pScrn, TIDAC_general_ctrl);
 
217
        save->dacregs[TIDAC_auxiliary_ctrl] =
 
218
                        S3InTiIndReg(pScrn, TIDAC_auxiliary_ctrl);
 
219
        S3OutTiIndReg(pScrn, TIDAC_general_io_ctrl, 0x00, 0x1f);
 
220
        save->dacregs[TIDAC_general_io_data] =
 
221
                        S3InTiIndReg(pScrn, TIDAC_general_io_data);
 
222
 
 
223
        if (pS3->RamDac->RamDacType == TI3025_RAMDAC) {
 
224
                save->dacregs[0x0e] = S3InTiIndReg(pScrn, 0x0e);
 
225
                save->dacregs[TIDAC_misc_ctrl] =
 
226
                        S3InTiIndReg(pScrn, TIDAC_misc_ctrl);
 
227
                S3OutTiIndReg(pScrn, TIDAC_pll_addr, 0x00, 0x00);
 
228
                save->dacregs[0x40] = S3InTiIndReg(pScrn, TIDAC_pll_pixel_data);
 
229
                S3OutTiIndReg(pScrn, TIDAC_pll_pixel_data, 0x00,
 
230
                              save->dacregs[0x40]);
 
231
                save->dacregs[0x41] = S3InTiIndReg(pScrn, TIDAC_pll_pixel_data);
 
232
                S3OutTiIndReg(pScrn, TIDAC_pll_pixel_data, 0x00,
 
233
                              save->dacregs[0x41]);
 
234
                save->dacregs[0x42] = S3InTiIndReg(pScrn, TIDAC_pll_pixel_data);
 
235
                S3OutTiIndReg(pScrn, TIDAC_pll_pixel_data, 0x00,
 
236
                              save->dacregs[0x42]);
 
237
                save->dacregs[0x43] = S3InTiIndReg(pScrn, TIDAC_pll_memory_data);
 
238
                S3OutTiIndReg(pScrn, TIDAC_pll_memory_data, 0x00,
 
239
                              save->dacregs[0x43]);
 
240
                save->dacregs[0x44] = S3InTiIndReg(pScrn, TIDAC_pll_memory_data);
 
241
                S3OutTiIndReg(pScrn, TIDAC_pll_memory_data, 0x00,
 
242
                              save->dacregs[0x44]);
 
243
                save->dacregs[0x45] = S3InTiIndReg(pScrn, TIDAC_pll_memory_data);
 
244
                S3OutTiIndReg(pScrn, TIDAC_pll_memory_data, 0x00,
 
245
                              save->dacregs[0x45]);
 
246
                save->dacregs[0x46] = S3InTiIndReg(pScrn, TIDAC_pll_loop_data);
 
247
                S3OutTiIndReg(pScrn, TIDAC_pll_loop_data, 0x00,
 
248
                              save->dacregs[0x46]);
 
249
                save->dacregs[0x47] = S3InTiIndReg(pScrn, TIDAC_pll_loop_data);
 
250
                S3OutTiIndReg(pScrn, TIDAC_pll_loop_data, 0x00,
 
251
                              save->dacregs[0x47]);
 
252
                save->dacregs[0x48] = S3InTiIndReg(pScrn, TIDAC_pll_loop_data);
 
253
                S3OutTiIndReg(pScrn, TIDAC_pll_loop_data, 0x00,
 
254
                              save->dacregs[0x48]);
 
255
        }
 
256
}
 
257
 
 
258
 
 
259
void S3TiDAC_Restore(ScrnInfoPtr pScrn)
 
260
{
 
261
        S3Ptr pS3 = S3PTR(pScrn);
 
262
        S3RegPtr restore = &pS3->SavedRegs;
 
263
 
 
264
        S3OutTiIndReg(pScrn, TIDAC_true_color_ctrl, 0x00,
 
265
                      restore->dacregs[TIDAC_true_color_ctrl]);
 
266
        S3OutTiIndReg(pScrn, TIDAC_multiplex_ctrl, 0x00,
 
267
                      restore->dacregs[TIDAC_multiplex_ctrl]);  
 
268
        S3OutTiIndReg(pScrn, TIDAC_clock_select, 0x00,
 
269
                      restore->dacregs[TIDAC_clock_select]);
 
270
        S3OutTiIndReg(pScrn, TIDAC_output_clock_select, 0x00,
 
271
                      restore->dacregs[TIDAC_output_clock_select]);
 
272
        S3OutTiIndReg(pScrn, TIDAC_general_ctrl, 0x00,
 
273
                      restore->dacregs[TIDAC_general_ctrl]);
 
274
        S3OutTiIndReg(pScrn, TIDAC_auxiliary_ctrl, 0x00,
 
275
                      restore->dacregs[TIDAC_auxiliary_ctrl]);
 
276
        S3OutTiIndReg(pScrn, TIDAC_general_io_ctrl, 0x00, 0x1f);
 
277
        S3OutTiIndReg(pScrn, TIDAC_general_io_data, 0x00,
 
278
                      restore->dacregs[TIDAC_general_io_data]);
 
279
        if (pS3->RamDac->RamDacType == TI3025_RAMDAC) {
 
280
                S3OutTiIndReg(pScrn, TIDAC_pll_addr, 0x00,
 
281
                              restore->dacregs[TIDAC_pll_addr]);
 
282
                S3OutTiIndReg(pScrn, TIDAC_pll_pixel_data, 0x00,
 
283
                              restore->dacregs[0x40]);
 
284
                S3OutTiIndReg(pScrn, TIDAC_pll_pixel_data, 0x00,
 
285
                              restore->dacregs[0x41]);
 
286
                S3OutTiIndReg(pScrn, TIDAC_pll_pixel_data, 0x00,
 
287
                              restore->dacregs[0x42]);
 
288
 
 
289
                S3OutTiIndReg(pScrn, TIDAC_pll_memory_data, 0x00,
 
290
                              restore->dacregs[0x43]);
 
291
                S3OutTiIndReg(pScrn, TIDAC_pll_memory_data, 0x00,
 
292
                              restore->dacregs[0x44]);
 
293
                S3OutTiIndReg(pScrn, TIDAC_pll_memory_data, 0x00,
 
294
                              restore->dacregs[0x45] | 0x80);
 
295
 
 
296
                S3OutTiIndReg(pScrn, TIDAC_pll_loop_data, 0x00,
 
297
                              restore->dacregs[0x46]);
 
298
                S3OutTiIndReg(pScrn, TIDAC_pll_loop_data, 0x00,
 
299
                              restore->dacregs[0x47]);
 
300
                S3OutTiIndReg(pScrn, TIDAC_pll_loop_data, 0x00,
 
301
                              restore->dacregs[0x48]);
 
302
 
 
303
                S3OutTiIndReg(pScrn, 0x0e, 0x00, restore->dacregs[0x0e]);
 
304
                S3OutTiIndReg(pScrn, TIDAC_misc_ctrl, 0x00,
 
305
                              restore->dacregs[TIDAC_misc_ctrl]);
 
306
        }
 
307
 
 
308
        S3OutTiIndReg(pScrn, TIDAC_ind_curs_ctrl, 0x00,
 
309
                      restore->dacregs[TIDAC_ind_curs_ctrl]);
 
310
}
 
311
 
 
312
 
 
313
void S3TiDAC_PreInit(ScrnInfoPtr pScrn)
 
314
{
 
315
        S3Ptr pS3 = S3PTR(pScrn);
 
316
        int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg;
 
317
        int mclk, m, n, p, mcc, cr5c;
 
318
 
 
319
        outb(vgaCRIndex, 0x5c);
 
320
        cr5c = inb(vgaCRReg);
 
321
        outb(vgaCRReg, cr5c & 0xdf);
 
322
 
 
323
        S3OutTiIndReg(pScrn, TIDAC_pll_addr, 0x00, 0x00);
 
324
        n = S3InTiIndReg(pScrn, TIDAC_pll_memory_data) & 0x7f;
 
325
        S3OutTiIndReg(pScrn, TIDAC_pll_addr, 0x00, 0x01);
 
326
        m = S3InTiIndReg(pScrn, TIDAC_pll_memory_data) & 0x7f;
 
327
        S3OutTiIndReg(pScrn, TIDAC_pll_addr, 0x00, 0x02);
 
328
        p = S3InTiIndReg(pScrn, TIDAC_pll_memory_data) & 0x03;
 
329
        mcc = S3InTiIndReg(pScrn, TIDAC_clock_ctrl);
 
330
        if (mcc & 0x08)
 
331
                mcc = (mcc & 0x07) * 2 + 2;
 
332
        else
 
333
                mcc = 1;
 
334
 
 
335
        mclk = ((1431818 * ((m+2) * 8)) / (n+2) / (1 << p) / mcc + 50) / 100;
 
336
        pS3->mclk = mclk;
 
337
        xf86DrvMsg(pScrn->scrnIndex, X_PROBED, "MCLK %1.3f MHz\n",
 
338
                   mclk / 1000.0);
 
339
 
 
340
        outb(vgaCRIndex, 0x5c);
 
341
        outb(vgaCRReg, cr5c);
 
342
}
 
343
 
 
344
 
 
345
static void S3TiDACCalcNMP(long freq, int *calc_n, int *calc_m, int *calc_p)
 
346
{
 
347
        double ffreq;
 
348
        int n, m, p;
 
349
        int best_n=32, best_m=32;
 
350
        double diff, mindiff;
 
351
 
 
352
        if (freq < FREQ_MIN)
 
353
                ffreq = FREQ_MIN / 1000.0;
 
354
        else if (freq > FREQ_MAX)
 
355
                ffreq = FREQ_MAX / 1000.0;
 
356
        else
 
357
                ffreq = freq / 1000.0;
 
358
 
 
359
        for (p=0; p<4 && ffreq<110.0; p++)
 
360
                ffreq *= 2;
 
361
#if FREQ_MIN < 110000/8
 
362
        if (p == 4) {
 
363
                ffreq /= 2;
 
364
                p--;
 
365
        }
 
366
#endif
 
367
 
 
368
        ffreq /= TI_REF_FREQ;
 
369
 
 
370
        mindiff = ffreq;
 
371
 
 
372
        for (n=1; n<=(int)(TI_REF_FREQ/0.5 - 2); n++) {
 
373
                m = (int)(ffreq * (n+2) / 8.0 + 0.5) - 2;
 
374
                if (m < 1)
 
375
                        m = 1;
 
376
                else if (m > 127)
 
377
                        m = 127;
 
378
 
 
379
                diff = ((m+2) * 8) / (n+2.0) - ffreq;
 
380
                if (diff < 0)
 
381
                        diff = -diff;
 
382
 
 
383
                if (diff < mindiff) {
 
384
                        mindiff = diff;
 
385
                        best_n = n;
 
386
                        best_m = m;
 
387
                }
 
388
        }
 
389
 
 
390
        *calc_n = best_n;
 
391
        *calc_m = best_m;
 
392
        *calc_p = p;
 
393
}
 
394
 
 
395
 
 
396
static void S3TiDACProgramClock(ScrnInfoPtr pScrn, int clk,
 
397
                                unsigned char n, unsigned char m,
 
398
                                unsigned char p)
 
399
{
 
400
        S3OutTiIndReg(pScrn, TIDAC_pll_addr, 0x00, 0x00);
 
401
 
 
402
        if (clk != TIDAC_pll_memory_data) {
 
403
                S3OutTiIndReg(pScrn, TIDAC_pll_pixel_data, 0x00, n);
 
404
                S3OutTiIndReg(pScrn, TIDAC_pll_pixel_data, 0x00, m);
 
405
                S3OutTiIndReg(pScrn, TIDAC_pll_pixel_data, 0x00, p | 0x08);
 
406
 
 
407
                S3OutTiIndReg(pScrn, TIDAC_pll_loop_data, 0x00, 0x01);
 
408
                S3OutTiIndReg(pScrn, TIDAC_pll_loop_data, 0x00, 0x01);
 
409
                S3OutTiIndReg(pScrn, TIDAC_pll_loop_data, 0x00, p > 0 ? p : 1);
 
410
                S3OutTiIndReg(pScrn, TIDAC_misc_ctrl, 0x00, 0x80 | 0x40 | 0x04);
 
411
 
 
412
                S3OutTiIndReg(pScrn, TIDAC_clock_select, 0x00, 0x05);
 
413
        } else {
 
414
                S3OutTiIndReg(pScrn, TIDAC_pll_memory_data, 0x00, n);
 
415
                S3OutTiIndReg(pScrn, TIDAC_pll_memory_data, 0x00, m);
 
416
                S3OutTiIndReg(pScrn, TIDAC_pll_memory_data, 0x00, p | 0x80);
 
417
        }
 
418
}
 
419
 
 
420
 
 
421
static void S3TiDACSetClock(ScrnInfoPtr pScrn, long freq, int clk)
 
422
{
 
423
        int m, n, p;
 
424
 
 
425
        S3TiDACCalcNMP(freq, &n, &m, &p);
 
426
 
 
427
        S3TiDACProgramClock(pScrn, clk, n, m, p);
 
428
}
 
429
 
 
430
 
 
431
 
 
432
void S3TiDAC_Init(ScrnInfoPtr pScrn, DisplayModePtr mode)
 
433
{
 
434
        S3Ptr pS3 = S3PTR(pScrn);
 
435
        vgaHWPtr hwp = VGAHWPTR(pScrn);
 
436
        vgaRegPtr pVga = &hwp->ModeReg;
 
437
        int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg;
 
438
        unsigned char tmp, tmp1, tmp2;
 
439
 
 
440
        S3TiDACSetClock(pScrn, mode->Clock, 2);
 
441
        outb(vgaCRIndex, 0x42);
 
442
        tmp = inb(vgaCRReg) & 0xf0;
 
443
        outb(vgaCRReg, tmp | 0x02);
 
444
        usleep(150000);
 
445
 
 
446
        outb(0x3c4, 1);
 
447
        tmp2 = inb(0x3c5);
 
448
        outb(0x3c5, tmp2 | 0x20);       /* blank */
 
449
 
 
450
        tmp = pVga->MiscOutReg;
 
451
        pVga->MiscOutReg |= 0xc0;
 
452
        tmp1 = 0x00;
 
453
        if (!(tmp & 0x80))
 
454
                tmp1 |= 0x02;
 
455
        if (!(tmp & 0x40))
 
456
                tmp1 |= 0x01;
 
457
 
 
458
        S3OutTiIndReg(pScrn, TIDAC_general_ctrl, 0x00, tmp1);
 
459
        S3OutTiIndReg(pScrn, 0x0e, 0x00, 0x00);
 
460
 
 
461
        /* XXX do 3020 input_clock_sel */
 
462
 
 
463
        outb(vgaCRIndex, 0x65);
 
464
        /* XXX 3025 */
 
465
        outb(vgaCRReg, 0x00);
 
466
 
 
467
        /* XXX 3025 */
 
468
        outb(vgaCRIndex, 0x40);
 
469
        outb(vgaCRReg, 0x11);
 
470
        outb(vgaCRIndex, 0x55);
 
471
        outb(vgaCRReg, 0x00);
 
472
 
 
473
        if (pScrn->bitsPerPixel > 8)
 
474
                S3OutTiIndReg(pScrn, TIDAC_auxiliary_ctrl, 0x00, 0x00);
 
475
        else
 
476
                S3OutTiIndReg(pScrn, TIDAC_auxiliary_ctrl, 0x00, 0x01);
 
477
 
 
478
        switch (pScrn->depth) {
 
479
        case 8:
 
480
                S3OutTiIndReg(pScrn, TIDAC_output_clock_select, 0x00,
 
481
                              0x4b);
 
482
                outb(vgaCRIndex, 0x66);
 
483
                tmp = inb(vgaCRReg);
 
484
                if (mode->Clock > 80000)
 
485
                        outb(vgaCRReg, (tmp & 0xf8) | 0x02);
 
486
                else
 
487
                        outb(vgaCRReg, (tmp & 0xf8) | 0x03);
 
488
                break;
 
489
        case 16:
 
490
                S3OutTiIndReg(pScrn, TIDAC_output_clock_select, 0x00,
 
491
                              0x4a);
 
492
                outb(vgaCRIndex, 0x66);
 
493
                tmp = inb(vgaCRReg);
 
494
                if (mode->Clock > 80000)
 
495
                        outb(vgaCRReg, (tmp & 0xf8) | 0x01);
 
496
                else
 
497
                        outb(vgaCRReg, (tmp & 0xf8) | 0x02);
 
498
                break;
 
499
        case 24:
 
500
                S3OutTiIndReg(pScrn, TIDAC_output_clock_select, 0x00,
 
501
                              (0x40 | 0x08 | 0x01));
 
502
                outb(vgaCRIndex, 0x66);
 
503
                tmp = inb(vgaCRReg);
 
504
                if (mode->Clock > 80000)
 
505
                        outb(vgaCRReg, (tmp & 0xf8) | 0x00);
 
506
                else
 
507
                        outb(vgaCRReg, (tmp & 0xf8) | 0x01);
 
508
                break;
 
509
        }
 
510
 
 
511
        outb(vgaCRIndex, 0x58);
 
512
        tmp = inb(vgaCRReg);
 
513
        outb(vgaCRReg, (tmp & 0xbf) | 0x40);
 
514
 
 
515
        switch(pScrn->depth) {
 
516
        case 8:
 
517
                S3OutTiIndReg(pScrn, TIDAC_true_color_ctrl, 0x00, 0x80);
 
518
                S3OutTiIndReg(pScrn, TIDAC_multiplex_ctrl, 0x00, 0x1c);
 
519
                break;
 
520
        case 15:
 
521
                S3OutTiIndReg(pScrn, TIDAC_true_color_ctrl, 0x00, 0x4c);
 
522
                S3OutTiIndReg(pScrn, TIDAC_multiplex_ctrl, 0x00, 0x04);
 
523
                S3OutTiIndReg(pScrn, TIDAC_key_ctrl, 0x00, 0x01);
 
524
                break;
 
525
        case 16:
 
526
                S3OutTiIndReg(pScrn, TIDAC_true_color_ctrl, 0x00, 0x4d);
 
527
                S3OutTiIndReg(pScrn, TIDAC_multiplex_ctrl, 0x00, 0x04);
 
528
                S3OutTiIndReg(pScrn, TIDAC_key_ctrl, 0x00, 0x01);
 
529
                break;
 
530
        case 24:
 
531
                S3OutTiIndReg(pScrn, TIDAC_true_color_ctrl, 0x00, 0x4e);
 
532
                S3OutTiIndReg(pScrn, TIDAC_multiplex_ctrl, 0x00, 0x04);
 
533
                S3OutTiIndReg(pScrn, TIDAC_key_ctrl, 0x00, 0x01);
 
534
                break;
 
535
        }
 
536
 
 
537
        S3OutTiIndReg(pScrn, TIDAC_general_io_ctrl, 0x00, 0x1f);
 
538
        S3OutTiIndReg(pScrn, TIDAC_general_io_data, 0x00, 0x01);
 
539
        S3OutTiIndReg(pScrn, TIDAC_general_io_ctrl, 0x00, 0x00);
 
540
        S3OutTiIndReg(pScrn, TIDAC_misc_ctrl, 0xf0, (0x04 | 0x08));
 
541
 
 
542
        outb(vgaCRIndex, 0x6d);
 
543
        if (pS3->s3Bpp == 1)
 
544
                if (mode->Clock > 80000)
 
545
                        outb(vgaCRReg, 0x02);
 
546
                else
 
547
                        outb(vgaCRReg, 0x03);
 
548
        else if (pS3->s3Bpp == 2)
 
549
                if (mode->Clock > 80000)
 
550
                        outb(vgaCRReg, 0x00);
 
551
                else
 
552
                        outb(vgaCRReg, 0x01);
 
553
        else
 
554
                outb(vgaCRReg, 0x00);
 
555
 
 
556
        S3OutTiIndReg(pScrn, TIDAC_sense_test, 0x00, 0x00);
 
557
 
 
558
        if (pS3->s3Bpp > 1)
 
559
        {
 
560
                int j;
 
561
 
 
562
                outb(0x3c6, 0xff);
 
563
                outb(0x3c8, 0x00);
 
564
                for(j=0; j<768; j++) {
 
565
                        outb(0x3c9, j);
 
566
                        outb(0x3c9, j);
 
567
                        outb(0x3c9, j);
 
568
                }
 
569
        }
 
570
 
 
571
        outb(0x3c4, 1);
 
572
        outb(0x3c5, tmp2);      /* unblank */
 
573
}
 
574
 
 
575
 
 
576
void S3TiLoadPalette(ScrnInfoPtr pScrn, int numColors, int *indicies, LOCO *colors,
 
577
                     VisualPtr pVisual)
 
578
{
 
579
        int i;
 
580
 
 
581
        outb(0x3c6, 0xff);
 
582
        outb(0x3c8, 0x00);
 
583
 
 
584
        for (i=0; i<768; i++) {
 
585
                outb(0x3c9, i);
 
586
                usleep(1000);
 
587
                outb(0x3c9, i);
 
588
                usleep(1000);
 
589
                outb(0x3c9, i);
 
590
                usleep(1000);
 
591
        }
 
592
}
 
593
 
 
594
 
 
595
 
 
596
/* hardware cursor */
 
597
 
 
598
static void S3TiSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg)
 
599
{
 
600
        S3Ptr pS3 = S3PTR(pScrn);
 
601
        int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg;
 
602
 
 
603
        /* unlock sys regs */
 
604
        outb(vgaCRIndex, 0x39);
 
605
        outb(vgaCRReg, 0xa5);
 
606
 
 
607
        S3OutTiIndReg(pScrn, TIDAC_cursor_color_0_red, 0x00,
 
608
                      (bg & 0x00FF0000) >> 16);
 
609
        S3OutTiIndReg(pScrn, TIDAC_cursor_color_0_green, 0x00,
 
610
                      (bg & 0x0000FF00) >> 8);
 
611
        S3OutTiIndReg(pScrn, TIDAC_cursor_color_0_blue, 0x00,
 
612
                      (bg & 0x000000FF));
 
613
 
 
614
        S3OutTiIndReg(pScrn, TIDAC_cursor_color_1_red, 0x00,
 
615
                      (fg & 0x00FF0000) >> 16);
 
616
        S3OutTiIndReg(pScrn, TIDAC_cursor_color_1_green, 0x00,
 
617
                      (fg & 0x0000FF00) >> 8);
 
618
        S3OutTiIndReg(pScrn, TIDAC_cursor_color_1_blue, 0x00,
 
619
                      (fg & 0x000000FF));
 
620
 
 
621
}
 
622
 
 
623
 
 
624
static void S3TiSetCursorPosition(ScrnInfoPtr pScrn, int x, int y)
 
625
{
 
626
        S3Ptr pS3 = S3PTR(pScrn);
 
627
        int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg;
 
628
 
 
629
        /* unlock sys regs */
 
630
        outb(vgaCRIndex, 0x39);
 
631
        outb(vgaCRReg, 0xa5);
 
632
        
 
633
        S3OutTiIndReg(pScrn, TIDAC_cursor_x_low, 0x00, x & 0xff);
 
634
        S3OutTiIndReg(pScrn, TIDAC_cursor_x_high, 0x00, (x >> 8) & 0x0f);
 
635
        S3OutTiIndReg(pScrn, TIDAC_cursor_y_low, 0x00, y & 0xff);
 
636
        S3OutTiIndReg(pScrn, TIDAC_cursor_y_high, 0x00, (y >> 8) & 0x0f);
 
637
}
 
638
 
 
639
 
 
640
static void S3TiHideCursor(ScrnInfoPtr pScrn)
 
641
{
 
642
        S3Ptr pS3 = S3PTR(pScrn);  
 
643
        int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg;
 
644
        
 
645
        /* unlock sys regs */
 
646
        outb(vgaCRIndex, 0x39);
 
647
        outb(vgaCRReg, 0xa5);
 
648
 
 
649
        S3OutTiIndReg(pScrn, TIDAC_ind_curs_ctrl, (unsigned char)
 
650
                      ~(0x40 | 0x10), 0x00);
 
651
}
 
652
 
 
653
 
 
654
static void S3TiShowCursor(ScrnInfoPtr pScrn)
 
655
{
 
656
        S3Ptr pS3 = S3PTR(pScrn);
 
657
        int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg;
 
658
        unsigned char tmp;
 
659
 
 
660
        /* unlock sys regs */
 
661
        outb(vgaCRIndex, 0x39);  
 
662
        outb(vgaCRReg, 0xa5);
 
663
        
 
664
        outb(vgaCRIndex, 0x55);
 
665
        tmp = inb(vgaCRReg) & 0xdf;
 
666
        outb(vgaCRReg, tmp | 0x20);
 
667
 
 
668
        outb(vgaCRIndex, 0x45);
 
669
        tmp = inb(vgaCRReg) & 0xdf;
 
670
        outb(vgaCRReg, tmp | 0x20);
 
671
 
 
672
        S3OutTiIndReg(pScrn, TIDAC_ind_curs_ctrl, (unsigned char)
 
673
                      ~(0x40 | 0x10), (0x40 | 0x10));
 
674
}
 
675
 
 
676
 
 
677
static void S3TiLoadCursorImage(ScrnInfoPtr pScrn, unsigned char *image)
 
678
{
 
679
        S3Ptr pS3 = S3PTR(pScrn);
 
680
        int vgaCRIndex = pS3->vgaCRIndex, vgaCRReg = pS3->vgaCRReg;
 
681
        unsigned char tmp, tmp1;
 
682
        register int i;
 
683
#if 0
 
684
        register unsigned char *mask = image + 1;
 
685
#endif
 
686
 
 
687
        /* unlock sys regs */
 
688
        outb(vgaCRIndex, 0x39);  
 
689
        outb(vgaCRReg, 0xa5);
 
690
        
 
691
        outb(vgaCRIndex, 0x55);
 
692
        tmp = inb(vgaCRReg) & 0xfc;
 
693
        outb(vgaCRReg, tmp | 0x01);
 
694
        tmp1 = inb(TI_INDEX_REG);
 
695
 
 
696
        outb(TI_INDEX_REG, TIDAC_cursor_ram_addr_low);
 
697
        outb(TI_DATA_REG, 0x00);
 
698
        outb(TI_INDEX_REG, TIDAC_cursor_ram_addr_high);
 
699
        outb(TI_DATA_REG, 0x00);
 
700
        outb(TI_INDEX_REG, TIDAC_cursor_ram_data);
 
701
 
 
702
#if 0
 
703
        for (i=0; i<512; i++, mask+=2)
 
704
                outb(TI_DATA_REG, *mask);
 
705
        for (i=0; i<512; i++, image+=2)
 
706
                outb(TI_DATA_REG, *image);
 
707
#else
 
708
        for (i=0; i<1024; i++) {
 
709
                outb(TI_DATA_REG, *image);
 
710
                image++;
 
711
        }
 
712
#endif
 
713
 
 
714
        outb(TI_INDEX_REG, tmp1);
 
715
 
 
716
        outb(vgaCRIndex, 0x55);
 
717
        outb(vgaCRReg, tmp);
 
718
}
 
719
 
 
720
 
 
721
 
 
722
static Bool S3TiUseHWCursor(ScreenPtr pScreen, CursorPtr pCurs)
 
723
{
 
724
        return TRUE;
 
725
}       
 
726
 
 
727
 
 
728
 
 
729
Bool S3Ti_CursorInit(ScreenPtr pScreen)
 
730
{
 
731
        ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
 
732
        S3Ptr pS3 = S3PTR(pScrn);
 
733
        xf86CursorInfoPtr pCurs;      
 
734
        
 
735
        if (!(pCurs = pS3->pCurs = xf86CreateCursorInfoRec()))
 
736
                return FALSE;
 
737
 
 
738
        pCurs->MaxWidth = 64;
 
739
        pCurs->MaxHeight = 64;
 
740
        pCurs->Flags = HARDWARE_CURSOR_TRUECOLOR_AT_8BPP |
 
741
                       HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1 |
 
742
                       HARDWARE_CURSOR_NIBBLE_SWAPPED |
 
743
                       HARDWARE_CURSOR_BIT_ORDER_MSBFIRST;
 
744
 
 
745
        pCurs->SetCursorColors = S3TiSetCursorColors;
 
746
        pCurs->SetCursorPosition = S3TiSetCursorPosition;
 
747
        pCurs->LoadCursorImage = S3TiLoadCursorImage;
 
748
        pCurs->HideCursor = S3TiHideCursor;
 
749
        pCurs->ShowCursor = S3TiShowCursor;
 
750
        pCurs->UseHWCursor = S3TiUseHWCursor;
 
751
        
 
752
        return xf86InitCursor(pScreen, pCurs);
 
753
}