sis_utility.c revision 1654201c
1/*
2 * SiS driver utility interface & routines
3 *
4 * Copyright (C) 2001-2005 by Thomas Winischhofer, Vienna, Austria.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1) Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2) Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 * 3) The name of the author may not be used to endorse or promote products
15 *    derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * Author: Thomas Winischhofer <thomas@winischhofer.net>
29 *
30 */
31
32#ifdef HAVE_CONFIG_H
33#include "config.h"
34#endif
35
36#include "sis.h"
37#include <X11/X.h>
38#include "dixstruct.h"
39
40#include "sis_videostr.h"
41
42#ifdef TWDEBUG
43#define SIS_NEED_orSISIDXREG
44#include "sis_regs.h"
45#endif
46
47/* Definitions for SISCTRL extension */
48
49#define SISCTRL_PROTOCOL_NAME	"SISCTRL"
50
51#define SISCTRL_MAJOR_VERSION		0	/* current version numbers */
52#define SISCTRL_MINOR_VERSION		1
53
54#define SISCTRL_MAX_SCREENS		32	/* number of screens the ext can handle */
55
56#define X_SiSCtrlQueryVersion		0
57#define X_SiSCtrlCommand		1
58
59#define SDC_ID				0x53495321
60
61#define SDC_VERSION			1
62
63#define SDC_NUM_PARM_RESULT		20
64
65/* sdc_command */
66#define SDC_CMD_GETVERSION 		0x98980001
67#define SDC_CMD_GETHWINFO		0x98980002
68#define SDC_CMD_GETALLFLAGS		0x98980003
69#define SDC_CMD_GETVBFLAGSVERSION	0x98980004
70#define SDC_CMD_GETVBFLAGS		0x98980005
71#define SDC_CMD_CHECKMODEFORCRT2	0x98980006
72#define SDC_CMD_SETVBFLAGS		0x98980007
73#define SDC_CMD_GETDETECTEDDEVICES	0x98980008
74#define SDC_CMD_REDETECTCRT2DEVICES	0x98980009
75#define SDC_CMD_GETCRT1STATUS		0x9898000a
76#define SDC_CMD_SETCRT1STATUS		0x9898000b
77#define SDC_CMD_GETSDFLAGS		0x9898000c
78#define SDC_CMD_GETSD2FLAGS		0x9898000d
79#define SDC_CMD_GETLOCKSTATUS		0x9898000e
80#define SDC_CMD_SETLOCKSTATUS		0x9898000f
81#define SDC_CMD_GETTVANTIFLICKER	0x98980010
82#define SDC_CMD_SETTVANTIFLICKER	0x98980011
83#define SDC_CMD_GETTVSATURATION		0x98980012
84#define SDC_CMD_SETTVSATURATION		0x98980013
85#define SDC_CMD_GETTVEDGEENHANCE	0x98980014
86#define SDC_CMD_SETTVEDGEENHANCE	0x98980015
87#define SDC_CMD_GETTVCFILTER		0x98980016
88#define SDC_CMD_SETTVCFILTER		0x98980017
89#define SDC_CMD_GETTVYFILTER		0x98980018
90#define SDC_CMD_SETTVYFILTER		0x98980019
91#define SDC_CMD_GETTVCOLORCALIB		0x9898001a
92#define SDC_CMD_SETTVCOLORCALIB		0x9898001b
93#define SDC_CMD_GETTVCHCONTRAST		0x9898001c
94#define SDC_CMD_SETTVCHCONTRAST		0x9898001d
95#define SDC_CMD_GETTVCHTEXTENHANCE	0x9898001e
96#define SDC_CMD_SETTVCHTEXTENHANCE	0x9898001f
97#define SDC_CMD_GETTVCHCHROMAFLICKERFILTER 0x98980020
98#define SDC_CMD_SETTVCHCHROMAFLICKERFILTER 0x98980021
99#define SDC_CMD_GETTVCHLUMAFLICKERFILTER 0x98980022
100#define SDC_CMD_SETTVCHLUMAFLICKERFILTER 0x98980023
101#define SDC_CMD_GETTVCHCVBSCOLOR	0x98980024
102#define SDC_CMD_SETTVCHCVBSCOLOR	0x98980025
103#define SDC_CMD_GETCHTVOVERSCAN		0x98980026
104#define SDC_CMD_SETCHTVOVERSCAN		0x98980027
105#define SDC_CMD_GETGAMMASTATUS		0x98980028
106#define SDC_CMD_SETGAMMASTATUS		0x98980029
107#define SDC_CMD_GETTVXSCALE		0x9898002a
108#define SDC_CMD_SETTVXSCALE		0x9898002b
109#define SDC_CMD_GETTVYSCALE		0x9898002c
110#define SDC_CMD_SETTVYSCALE		0x9898002d
111#define SDC_CMD_GETSCREENSIZE		0x9898002e
112#define SDC_CMD_GETGAMMABRIGHTNESS	0x9898002f
113#define SDC_CMD_SETGAMMABRIGHTNESS	0x98980030
114#define SDC_CMD_GETGAMMABRIGHTNESS2	0x98980031
115#define SDC_CMD_SETGAMMABRIGHTNESS2	0x98980032
116#define SDC_CMD_GETGETGAMMACRT2		0x98980033
117#define SDC_CMD_SETGETGAMMACRT2		0x98980034
118#define SDC_CMD_GETHWCURSORSTATUS	0x98980035
119#define SDC_CMD_SETHWCURSORSTATUS	0x98980036
120#define SDC_CMD_GETPANELMODE		0x98980037
121#define SDC_CMD_SETPANELMODE		0x98980038
122#define SDC_CMD_GETMERGEDMODEDETAILS	0x98980039
123#define SDC_CMD_GETDEVICENAME		0x9898003a
124#define SDC_CMD_GETMONITORNAME		0x9898003b
125#define SDC_CMD_GETDEVICENAME2		0x9898003c
126#define SDC_CMD_GETMONITORNAME2		0x9898003d
127#define SDC_CMD_SETXVBRIGHTNESS		0x9898003e
128#define SDC_CMD_GETXVBRIGHTNESS		0x9898003f
129#define SDC_CMD_SETXVCONTRAST		0x98980040
130#define SDC_CMD_GETXVCONTRAST		0x98980041
131#define SDC_CMD_SETXVHUE		0x98980042
132#define SDC_CMD_GETXVHUE		0x98980043
133#define SDC_CMD_SETXVSATURATION		0x98980044
134#define SDC_CMD_GETXVSATURATION		0x98980045
135#define SDC_CMD_SETXVGAMMA		0x98980046
136#define SDC_CMD_GETXVGAMMA		0x98980047
137#define SDC_CMD_SETXVCOLORKEY		0x98980048
138#define SDC_CMD_GETXVCOLORKEY		0x98980049
139#define SDC_CMD_SETXVAUTOPAINTCOLORKEY	0x9898004a
140#define SDC_CMD_GETXVAUTOPAINTCOLORKEY	0x9898004b
141#define SDC_CMD_SETXVDEFAULTS		0x9898004c
142#define SDC_CMD_SETXVDISABLEGFX		0x9898004d
143#define SDC_CMD_GETXVDISABLEGFX		0x9898004e
144#define SDC_CMD_SETXVDISABLEGFXLR	0x9898004f
145#define SDC_CMD_GETXVDISABLEGFXLR	0x98980050
146#define SDC_CMD_SETXVSWITCHCRT		0x98980051
147#define SDC_CMD_GETXVSWITCHCRT		0x98980052
148#define SDC_CMD_GETTVXPOS		0x98980053
149#define SDC_CMD_SETTVXPOS		0x98980054
150#define SDC_CMD_GETTVYPOS		0x98980055
151#define SDC_CMD_SETTVYPOS		0x98980056
152#define SDC_CMD_SETXVDEINT		0x98980057
153#define SDC_CMD_GETXVDEINT		0x98980058
154#define SDC_CMD_GETMONGAMMACRT1		0x98980059
155#define SDC_CMD_GETMONGAMMACRT2		0x9898005a
156#define SDC_CMD_LOGQUIET		0x9898005b
157#define SDC_CMD_GETNEWGAMMABRICON	0x9898005c
158#define SDC_CMD_SETNEWGAMMABRICON	0x9898005d
159#define SDC_CMD_GETNEWGAMMABRICON2	0x9898005e
160#define SDC_CMD_SETNEWGAMMABRICON2	0x9898005f
161#define SDC_CMD_GETGETNEWGAMMACRT2	0x98980060
162#define SDC_CMD_SETGETNEWGAMMACRT2	0x98980061
163#define SDC_CMD_NEWSETVBFLAGS		0x98980062
164#define SDC_CMD_GETCRT1SATGAIN		0x98980063
165#define SDC_CMD_SETCRT1SATGAIN		0x98980064
166#define SDC_CMD_GETCRT2SATGAIN		0x98980065
167#define SDC_CMD_SETCRT2SATGAIN		0x98980066
168/* more to come, adapt MAXCOMMAND! */
169#define SDC_MAXCOMMAND			SDC_CMD_SETCRT2SATGAIN
170
171/* in result_header */
172#define SDC_RESULT_OK  			0x66670000
173#define SDC_RESULT_UNDEFCMD		0x66670001
174#define SDC_RESULT_NOPERM		0x66670002
175#define SDC_RESULT_INVAL		0x66670003
176#define SDC_RESULT_MESSAGEERROR		0x66670004  /* Client side only */
177#define SDC_RESULT_NOEXTENSION		0x66670005  /* Client side only */
178
179/* For SDC_CMD_GETHWINFO */
180#define SDC_BUS_TYPE_PCI		0
181#define SDC_BUS_TYPE_AGP		1
182#define SDC_BUS_TYPE_PCIE		2
183#define SDC_BUS_TYPE_USB		3
184
185/* For SDC_CMD_GETMERGEDMODEDETAILS */
186#define SDC_MMODE_POS_ERROR		0
187#define SDC_MMODE_POS_LEFTOF		1
188#define SDC_MMODE_POS_RIGHTOF		2
189#define SDC_MMODE_POS_ABOVE		3
190#define SDC_MMODE_POS_BELOW		4
191#define SDC_MMODE_POS_CLONE		5
192
193typedef struct _SiSCtrlQueryVersion {
194    CARD8	reqType;		/* always SiSCtrlReqCode */
195    CARD8	SiSCtrlReqType;		/* always X_SiSCtrlQueryVersion */
196    CARD16	length B16;
197} xSiSCtrlQueryVersionReq;
198#define sz_xSiSCtrlQueryVersionReq	4
199
200typedef struct {
201    BYTE	type;			/* X_Reply */
202    BOOL	pad1;
203    CARD16	sequenceNumber B16;
204    CARD32	length B32;
205    CARD16	majorVersion B16;	/* major version of SISCTRL */
206    CARD16	minorVersion B16;	/* minor version of SISCTRL */
207    CARD32	pad2 B32;
208    CARD32	pad3 B32;
209    CARD32	pad4 B32;
210    CARD32	pad5 B32;
211    CARD32	pad6 B32;
212} xSiSCtrlQueryVersionReply;
213#define sz_xSiSCtrlQueryVersionReply	32
214
215typedef struct {
216    CARD8	reqType;		/* always SiSCtrlReqCode */
217    CARD8	SiSCtrlReqType;		/* always SiSCtrl_SiSCtrlCommand */
218    CARD16	length B16;
219    CARD32	pad1 B32;
220    CARD32	screen;
221    CARD32 	sdc_id;
222    CARD32 	sdc_chksum;
223    CARD32	sdc_command;
224    CARD32	sdc_parm[SDC_NUM_PARM_RESULT];
225    CARD32	sdc_result_header;
226    CARD32	sdc_result[SDC_NUM_PARM_RESULT];
227    char	sdc_buffer[32];
228} xSiSCtrlCommandReq;
229#define sz_xSiSCtrlCommandReq		(28 + (SDC_NUM_PARM_RESULT * 4 * 2) + 32)
230
231typedef struct {
232    BYTE	type;			/* X_Reply */
233    BOOL	pad1;
234    CARD16	sequenceNumber B16;
235    CARD32	length B32;
236    CARD32	screen;
237    CARD32 	sdc_id;
238    CARD32 	sdc_chksum;
239    CARD32	sdc_command;
240    CARD32	sdc_parm[SDC_NUM_PARM_RESULT];
241    CARD32	sdc_result_header;
242    CARD32	sdc_result[SDC_NUM_PARM_RESULT];
243    char	sdc_buffer[32];
244} xSiSCtrlCommandReply;
245#define sz_xSiSCtrlCommandReply		(28 + (SDC_NUM_PARM_RESULT * 4 * 2) + 32)
246
247typedef struct {
248    unsigned int maxscreens;		/* Max number of entries = SISCTRL_MAX_SCREENS*/
249    unsigned int version_major;		/* Extension major version */
250    unsigned int version_minor; 	/* Extension minor version */
251    int		 (*HandleSiSDirectCommand[SISCTRL_MAX_SCREENS])(xSiSCtrlCommandReply *);
252} xSiSCtrlScreenTable;
253
254void		SiSCtrlExtInit(ScrnInfoPtr pScrn);
255void		SiSCtrlExtUnregister(SISPtr pSiS, int index);
256
257#ifdef XV_SD_DEPRECATED
258int		SISSetPortUtilAttribute(ScrnInfoPtr pScrn, Atom attribute,
259					INT32 value, SISPortPrivPtr pPriv);
260int		SISGetPortUtilAttribute(ScrnInfoPtr pScrn,  Atom attribute,
261					INT32 *value, SISPortPrivPtr pPriv);
262#endif
263
264extern Bool 	SISRedetectCRT2Type(ScrnInfoPtr pScrn);
265extern UShort	SiS_CheckModeCRT1(ScrnInfoPtr pScrn, DisplayModePtr mode,
266				 unsigned int VBFlags, Bool hcm);
267extern UShort	SiS_CheckModeCRT2(ScrnInfoPtr pScrn, DisplayModePtr mode,
268				 unsigned int VBFlags, Bool hcm);
269extern void	SISAdjustFrame(ADJUST_FRAME_ARGS_DECL);
270extern float	SiSCalcVRate(DisplayModePtr mode);
271extern void	SiS_UpdateGammaCRT2(ScrnInfoPtr pScrn);
272#ifdef SISGAMMARAMP
273extern void	SISCalculateGammaRamp(ScreenPtr pScreen, ScrnInfoPtr pScrn);
274#endif
275
276extern void	SISSetPortDefaults(ScrnInfoPtr pScrn, SISPortPrivPtr pPriv);
277extern void	SISUpdateVideoParms(SISPtr pSiS, SISPortPrivPtr pPriv);
278extern void	SiSUpdateXvGamma(SISPtr pSiS, SISPortPrivPtr pPriv);
279
280/***********************************
281 *        Low-level routines       *
282 ***********************************/
283
284static Bool
285SISSwitchCRT1Status(ScrnInfoPtr pScrn, int onoff, Bool quiet)
286{
287    SISPtr pSiS = SISPTR(pScrn);
288    DisplayModePtr mode = pScrn->currentMode;
289    ULong vbflags = pSiS->VBFlags;
290    ULong vbflags3 = pSiS->VBFlags3;
291    int crt1off;
292
293    /* onoff: 0=OFF, 1=ON(VGA), 2=ON(LCDA) */
294
295    /* Switching to LCDA will disable CRT2 if previously LCD or VGA,
296     * unless on a dual-vb setup
297     */
298
299    /* For usability reasons, the user should not simply "lose" one
300     * of his output devices in MergedFB mode. Therefore, a switch
301     * which might lead to this situation will not be performed in
302     * MergedFB mode. (For example: If CRT2 is either LCD or VGA,
303     * don't let the user switch to LCD-via-CRT1 mode, because he
304     * would lose one output device since LCD-via-CRT1 is only
305     * supported together with TV, not any other CRT2 type.)
306     * In Non-MergedFB mode, losing one output device is not
307     * considered that harmful.
308     * Update: We let the user switch off a device if currently
309     * a "clone" mode is active. Same for switching CRT1 to LCD
310     * while CRT2 is LCD or VGA.
311     */
312
313    /* Do NOT use this to switch from CRT1_LCDA to CRT2_LCD */
314
315    /* Only on 300 and 315/330/340 series */
316    if(pSiS->VGAEngine != SIS_300_VGA &&
317       pSiS->VGAEngine != SIS_315_VGA) return FALSE;
318
319    /* Off only if at least one CRT2 device is active */
320    if((!onoff) && (!(vbflags & CRT2_ENABLE))) return FALSE;
321
322#ifdef SISDUALHEAD
323    if(pSiS->DualHeadMode) return FALSE;
324#endif
325
326    /* Can't switch to LCDA if not supported (duh!) */
327    if(!(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTLCDA)) {
328       if(onoff == 2) {
329          if(!quiet) {
330             xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
331	        "LCD-via-CRT1 not supported by hardware or no panel detected\n");
332	  }
333          return FALSE;
334       }
335    }
336
337#ifdef SISMERGED
338    if(pSiS->MergedFB) {
339       if(((SiSMergedDisplayModePtr)mode->Private)->CRT2Position != sisClone) {
340          if(!onoff) {
341             if(!quiet) {
342                xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
343	           "CRT1 can't be switched off in MergedFB mode unless a clone mode is active\n");
344	     }
345             return FALSE;
346          } else if(onoff == 2) {
347             if(!(pSiS->SiS_SD3_Flags & SiS_SD3_SUPPORTDUALDVI)) {
348                if(vbflags & (CRT2_LCD|CRT2_VGA)) {
349	           if(!quiet) {
350	              xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
351	   	         "CRT1 type can only be VGA while CRT2 is LCD or VGA\n");
352	           }
353                   return FALSE;
354                }
355	     }
356          }
357       }
358       if(mode->Private) {
359	  mode = ((SiSMergedDisplayModePtr)mode->Private)->CRT1;
360       }
361    }
362#endif
363
364    vbflags &= ~(DISPTYPE_CRT1 | SINGLE_MODE | MIRROR_MODE | CRT1_LCDA);
365    vbflags3 &= ~(VB3_CRT1_TV | VB3_CRT1_LCD | VB3_CRT1_VGA);
366    crt1off = 1;
367    if(onoff > 0) {
368       vbflags |= DISPTYPE_CRT1;
369       crt1off = 0;
370       if(onoff == 2) {
371	  vbflags |= CRT1_LCDA;
372	  vbflags3 |= VB3_CRT1_LCD;
373	  if(!(pSiS->SiS_SD3_Flags & SiS_SD3_SUPPORTDUALDVI)) {
374	     vbflags &= ~(CRT2_LCD|CRT2_VGA);
375	  }
376       } else {
377          vbflags3 |= VB3_CRT1_VGA;
378       }
379       /* Remember: Dualhead not supported */
380       if(vbflags & CRT2_ENABLE) vbflags |= MIRROR_MODE;
381       else vbflags |= SINGLE_MODE;
382    } else {
383       vbflags |= SINGLE_MODE;
384    }
385
386    if(vbflags & CRT1_LCDA) {
387       if(SiS_CheckModeCRT1(pScrn, mode, vbflags, pSiS->HaveCustomModes) < 0x14) {
388          if(!quiet) {
389             xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
390		"Current mode not suitable for LCD-via-CRT1\n");
391	  }
392          return FALSE;
393       }
394    }
395
396    pSiS->CRT1off = crt1off;
397    pSiS->VBFlags = pSiS->VBFlags_backup = vbflags;
398    pSiS->VBFlags3 = pSiS->VBFlags_backup3 = vbflags3;
399
400    /* Sync the accelerators */
401    (*pSiS->SyncAccel)(pScrn);
402
403    pSiS->skipswitchcheck = TRUE;
404    if(!(pScrn->SwitchMode(SWITCH_MODE_ARGS(pScrn, pScrn->currentMode)))) {
405       pSiS->skipswitchcheck = FALSE;
406       return FALSE;
407    }
408    pSiS->skipswitchcheck = FALSE;
409    SISAdjustFrame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0));
410    return TRUE;
411}
412
413static Bool
414SISRedetectCRT2Devices(ScrnInfoPtr pScrn)
415{
416    SISPtr pSiS = SISPTR(pScrn);
417
418    if((pSiS->VGAEngine != SIS_300_VGA) && (pSiS->VGAEngine != SIS_315_VGA)) {
419       return FALSE;
420    }
421
422#ifdef SISDUALHEAD
423    if(pSiS->DualHeadMode) return FALSE;
424#endif
425
426    /* Sync the accelerators */
427    (*pSiS->SyncAccel)(pScrn);
428
429    if(SISRedetectCRT2Type(pScrn)) {
430       /* If this returns TRUE, we need to reset the display mode */
431       /* Sync the accelerators */
432       (*pSiS->SyncAccel)(pScrn);
433       pSiS->skipswitchcheck = TRUE;
434       if(!(pScrn->SwitchMode(SWITCH_MODE_ARGS(pScrn, pScrn->currentMode)))) {
435          pSiS->skipswitchcheck = FALSE;
436          return FALSE;
437       }
438       pSiS->skipswitchcheck = FALSE;
439       SISAdjustFrame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0));
440    }
441    return TRUE;
442}
443
444static Bool
445SISSwitchCRT2Type(ScrnInfoPtr pScrn, ULong newvbflags, Bool quiet)
446{
447    SISPtr pSiS = SISPTR(pScrn);
448    Bool hcm = pSiS->HaveCustomModes;
449    DisplayModePtr mode = pScrn->currentMode;
450
451    /* Do NOT use this to switch from CRT2_LCD to CRT1_LCDA */
452
453    /* Switching CRT2 to LCD or VGA will switch CRT1 to VGA if
454     * previously LCD-via-CRT1
455     */
456
457    /* For usability reasons, the user should not simply "lose" one
458     * of his output devices in MergedFB mode. Therefore, a switch
459     * which might lead to this situation will not be performed in
460     * MergedFB mode. (For example: If CRT1 is LCD-via-CRT1, don't
461     * let the user switch CRT2 to LCD or VGA mode, because he
462     * would lose one output device since LCD-via-CRT1 is only
463     * supported together with TV, not any other CRT2 type.)
464     * In Non-MergedFB mode, losing one output device is not
465     * considered that harmful.
466     * Update: We allow this if currently a "clone" display mode
467     * is active.
468     */
469
470    /* Only on 300 and 315/330/340 series */
471    if(pSiS->VGAEngine != SIS_300_VGA &&
472       pSiS->VGAEngine != SIS_315_VGA) return FALSE;
473
474    /* Only if there is a video bridge */
475    if(!(pSiS->VBFlags2 & VB2_VIDEOBRIDGE)) return FALSE;
476
477#ifdef SISDUALHEAD
478    if(pSiS->DualHeadMode) return FALSE;
479#endif
480
481#define SiS_NewVBMask (CRT2_ENABLE|CRT1_LCDA|TV_PAL|TV_NTSC|TV_PALM|TV_PALN|TV_NTSCJ| \
482		       TV_AVIDEO|TV_SVIDEO|TV_SCART|TV_HIVISION|TV_YPBPR|TV_YPBPRALL|\
483		       TV_YPBPRAR)
484
485    newvbflags &= SiS_NewVBMask;
486    newvbflags |= pSiS->VBFlags & ~SiS_NewVBMask;
487
488    if(!(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTLCDA)) {
489       newvbflags &= ~CRT1_LCDA;
490    }
491    if(!(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTHIVISION)) {
492       newvbflags &= ~TV_HIVISION;
493    }
494    if(!(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTYPBPR)) {
495       newvbflags &= ~TV_YPBPR;
496    }
497
498#ifdef SISMERGED
499    if(pSiS->MergedFB) {
500       if((mode->Private) &&
501          ((SiSMergedDisplayModePtr)mode->Private)->CRT2Position != sisClone) {
502          if(!(newvbflags & CRT2_ENABLE)) {
503             if(!quiet) {
504	        xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
505	           "CRT2 can't be switched off in MergedFB mode unless a clone mode is active\n");
506	     }
507	     return FALSE;
508          }
509          if(!(pSiS->SiS_SD3_Flags & SiS_SD3_SUPPORTDUALDVI)) {
510             if((newvbflags & (CRT2_LCD|CRT2_VGA)) && (newvbflags & CRT1_LCDA)) {
511                if(!quiet) {
512	           xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
513	              "CRT2 type can only be TV while in LCD-via-CRT1 mode\n");
514	        }
515	        return FALSE;
516	     }
517          }
518       }
519       hcm = pSiS->HaveCustomModes2;
520       if(mode->Private) {
521	  mode = ((SiSMergedDisplayModePtr)mode->Private)->CRT2;
522       }
523    }
524#endif
525
526    if((!(newvbflags & CRT2_ENABLE)) && (!newvbflags & DISPTYPE_CRT1)) {
527       if(!quiet) {
528          xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
529             "CRT2 can't be switched off while CRT1 is off\n");
530       }
531       return FALSE;
532    }
533
534    /* CRT2_LCD and CRT2_VGA overrule LCDA (in non-MergedFB mode) */
535    if(!(pSiS->SiS_SD3_Flags & SiS_SD3_SUPPORTDUALDVI)) {
536       if(newvbflags & (CRT2_LCD|CRT2_VGA)) {
537          newvbflags &= ~CRT1_LCDA;
538       }
539    }
540
541    /* Check if the current mode is suitable for desired output device (if any) */
542    if(SiS_CheckModeCRT2(pScrn, mode, newvbflags, hcm) < 0x14) {
543       if(!quiet) {
544          xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
545	     "Current mode not suitable for desired CRT2 output device\n");
546       }
547       return FALSE;
548    }
549
550    /* Remember: Dualhead not supported */
551    newvbflags &= ~(SINGLE_MODE | MIRROR_MODE);
552    if((newvbflags & DISPTYPE_CRT1) && (newvbflags & CRT2_ENABLE)) {
553       newvbflags |= MIRROR_MODE;
554    } else {
555       newvbflags |= SINGLE_MODE;
556    }
557
558    /* Sync the accelerators */
559    (*pSiS->SyncAccel)(pScrn);
560
561    pSiS->VBFlags = pSiS->VBFlags_backup = newvbflags;
562
563    pSiS->skipswitchcheck = TRUE;
564    if(!(pScrn->SwitchMode(SWITCH_MODE_ARGS(pScrn, pScrn->currentMode)))) {
565       pSiS->skipswitchcheck = FALSE;
566       return FALSE;
567    }
568    pSiS->skipswitchcheck = FALSE;
569    SISAdjustFrame(ADJUST_FRAME_ARGS(pScrn, pScrn->frameX0, pScrn->frameY0));
570    return TRUE;
571}
572
573static Bool
574SISSwitchOutputType(ScrnInfoPtr pScrn, ULong newvbflags, ULong newvbflags3,
575		ULong newvbflags4, Bool quiet)
576{
577    /* For future use */
578
579    return FALSE;
580}
581
582static ULong
583SiSCondToVBFlags(UShort cond, ULong GivenVBFlags)
584{
585    ULong vbflags = GivenVBFlags;
586
587    /* No special treatment for NTSC-J here; conditions equal NTSC */
588    if(cond) {
589       vbflags &= ~(CRT2_ENABLE | CRT1_LCDA | TV_STANDARD | TV_INTERFACE);
590       if((cond & SiS_CF2_TYPEMASK) == SiS_CF2_LCD) {
591	  vbflags |= CRT2_LCD;
592       } else if((cond & SiS_CF2_TYPEMASK) == SiS_CF2_TV) {
593	  vbflags |= (CRT2_TV | TV_SVIDEO);
594	  if(cond & SiS_CF2_TVPAL)  	  vbflags |= TV_PAL;
595	  else if(cond & SiS_CF2_TVPALM)  vbflags |= (TV_PAL | TV_PALM);
596	  else if(cond & SiS_CF2_TVPALN)  vbflags |= (TV_PAL | TV_PALN);
597	  else if(cond & SiS_CF2_TVNTSC)  vbflags |= TV_NTSC;
598       } else if((cond & SiS_CF2_TYPEMASK) == SiS_CF2_TVSPECIAL) {
599          vbflags |= CRT2_TV;
600	  if((cond & SiS_CF2_TVSPECMASK) == SiS_CF2_TVHIVISION)
601		vbflags |= TV_HIVISION;
602	  else if((cond & SiS_CF2_TVSPECMASK) == SiS_CF2_TVYPBPR525I)
603		vbflags |= (TV_YPBPR | TV_YPBPR525I);
604	  else if((cond & SiS_CF2_TVSPECMASK) == SiS_CF2_TVYPBPR525P)
605		vbflags |= (TV_YPBPR | TV_YPBPR525P);
606	  else if((cond & SiS_CF2_TVSPECMASK) == SiS_CF2_TVYPBPR625I)
607		vbflags |= (TV_YPBPR | TV_YPBPR625I);
608	  else if((cond & SiS_CF2_TVSPECMASK) == SiS_CF2_TVYPBPR625P)
609		vbflags |= (TV_YPBPR | TV_YPBPR625P);
610	  else if((cond & SiS_CF2_TVSPECMASK) == SiS_CF2_TVYPBPR750P)
611		vbflags |= (TV_YPBPR | TV_YPBPR750P);
612	  else if((cond & SiS_CF2_TVSPECMASK) == SiS_CF2_TVYPBPR1080I)
613		vbflags |= (TV_YPBPR | TV_YPBPR1080I);
614       } else if((cond & SiS_CF2_TYPEMASK) == SiS_CF2_VGA2) {
615	  vbflags |= CRT2_VGA;
616       } else if((cond & SiS_CF2_TYPEMASK) == SiS_CF2_CRT1LCDA) {
617	  vbflags |= CRT1_LCDA;
618       }
619    }
620    return(vbflags);
621}
622
623static int
624SISCheckModeForCRT2Type(ScrnInfoPtr pScrn, DisplayModePtr mode, ULong vbflags, UShort cond, Bool quiet)
625{
626    SISPtr pSiS = SISPTR(pScrn);
627    DisplayModePtr mastermode;
628    Bool hcm = pSiS->HaveCustomModes;
629    int result = 0;
630
631    mastermode = mode;
632
633#ifdef SISDUALHEAD
634    if((!pSiS->DualHeadMode) || (!pSiS->SecondHead)) {
635#endif
636
637       if(vbflags & CRT2_ENABLE) {
638
639#ifdef SISMERGED
640          if(pSiS->MergedFB) {
641             hcm = pSiS->HaveCustomModes2;
642             if(mode->Private) {
643	        mode = ((SiSMergedDisplayModePtr)mode->Private)->CRT2;
644             }
645          }
646#endif
647
648          /* For RandR */
649          if((mode->HDisplay > pScrn->virtualX) || (mode->VDisplay > pScrn->virtualY)) {
650             if(!quiet) {
651                xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
652		    "Desired mode too large for current screen size\n");
653             }
654             result |= 0x02;
655          }
656
657          /* Check if the desired mode is suitable for current CRT2 output device */
658          if(SiS_CheckModeCRT2(pScrn, mode, vbflags, hcm) < 0x14) {
659             if((!cond) && (!quiet)) {
660                xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
661		    "Desired mode not suitable for current CRT2 output device\n");
662             }
663             result |= 0x01;
664          }
665
666       }
667
668#ifdef SISDUALHEAD
669    }
670#endif
671
672    mode = mastermode;
673
674#ifdef SISDUALHEAD
675    if((!pSiS->DualHeadMode) || (pSiS->SecondHead)) {
676#endif
677
678       if(vbflags & CRT1_LCDA) {
679
680#ifdef SISMERGED
681          if(pSiS->MergedFB) {
682             hcm = pSiS->HaveCustomModes;
683             if(mode->Private) {
684	        mode = ((SiSMergedDisplayModePtr)mode->Private)->CRT1;
685	     }
686          }
687#endif
688
689	  /* For RandR */
690	  if((mode->HDisplay > pScrn->virtualX) || (mode->VDisplay > pScrn->virtualY)) {
691	     if(!quiet) {
692		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
693			"Desired mode too large for current screen size\n");
694	     }
695	     result |= 0x02;
696	  }
697
698	  /* Check if the desired mode is suitable for current CRT1 output device */
699	  if(SiS_CheckModeCRT1(pScrn, mode, vbflags, hcm) < 0x14) {
700	     if((!cond) && (!quiet)) {
701		xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
702		      "Desired mode not suitable for current CRT1 output device\n");
703	     }
704	     result |= 0x01;
705	  }
706
707       }
708
709#ifdef SISDUALHEAD
710    }
711#endif
712
713    return result;
714}
715
716#ifdef XV_SD_DEPRECATED
717static int
718SISCheckModeIndexForCRT2Type(ScrnInfoPtr pScrn, UShort cond, UShort index, Bool quiet)
719{
720    SISPtr pSiS = SISPTR(pScrn);
721    DisplayModePtr mode = pScrn->modes;
722    ULong vbflags;
723    int i;
724
725    /* Not only CRT2, but also LCDA */
726
727    /* returns 0 if mode ok,
728     *         0x01 if mode not ok for CRT2 device,
729     *         0x02 if mode too large for current root window
730     *         or combinations thereof
731     */
732
733    vbflags = SiSCondToVBFlags(cond, pSiS->VBFlags);
734
735    /* Find mode of given index */
736    if(index) {
737       for(i = 0; i < index; i++) {
738          if(!mode) return 0x03;
739          mode = mode->next;
740       }
741    }
742
743    return(SISCheckModeForCRT2Type(pScrn, mode, vbflags, cond, quiet));
744}
745#endif
746
747static DisplayModePtr
748sisFindModeFromTiming(ScrnInfoPtr pScrn, UShort hdisplay,
749			      UShort vdisplay, UShort htotal, UShort vtotal,
750			      UShort hsyncstart, UShort hsyncend, UShort vsyncstart,
751			      UShort vsyncend, int clock)
752{
753   DisplayModePtr mode = pScrn->modes, pmode = pScrn->modes;
754   Bool found = FALSE;
755
756   do {
757       if( (mode->HDisplay == hdisplay) &&
758           (mode->VDisplay == vdisplay) &&
759	   (mode->HTotal == htotal) &&
760	   (mode->VTotal == vtotal) &&
761	   (mode->HSyncStart == hsyncstart) &&
762	   (mode->VSyncStart == vsyncstart) &&
763	   (mode->HSyncEnd == hsyncend) &&
764	   (mode->VSyncEnd == vsyncend) &&
765	   (mode->Clock == clock) ) {
766	  found = TRUE;
767	  break;
768       }
769       mode = mode->next;
770    } while((mode) && (mode != pmode));
771
772    if(found) return mode;
773    else      return NULL;
774}
775
776static int
777SISCheckModeTimingForCRT2Type(ScrnInfoPtr pScrn, UShort cond, UShort hdisplay,
778			      UShort vdisplay, UShort htotal, UShort vtotal,
779			      UShort hsyncstart, UShort hsyncend, UShort vsyncstart,
780			      UShort vsyncend, int clock, Bool quiet)
781{
782    SISPtr pSiS = SISPTR(pScrn);
783    DisplayModePtr mode;
784    ULong vbflags;
785
786    /* Not only CRT2, but also LCDA */
787
788    /* returns 0 if mode ok,
789     *         0x01 if mode not ok for CRT2 device,
790     *         0x02 if mode too large for current root window
791     *         or combinations thereof
792     */
793
794    vbflags = SiSCondToVBFlags(cond, pSiS->VBFlags);
795
796    /* Find mode with given timing */
797    mode = sisFindModeFromTiming(pScrn, hdisplay, vdisplay, htotal, vtotal,
798				hsyncstart, hsyncend, vsyncstart, vsyncend,
799				clock);
800    if(!mode) return 0x03;
801
802    return(SISCheckModeForCRT2Type(pScrn, mode, vbflags, cond, quiet));
803}
804
805#ifdef SISMERGED
806static void
807SISGetMergedModeDetails(ScrnInfoPtr pScrn,
808	   int hd, int vd, int ht, int vt, int hss, int hse, int vss, int vse, int clk,
809	   unsigned int *pos, unsigned int *crt1x, unsigned int *crt1y,
810	   unsigned int *crt1clk, unsigned int *crt2x, unsigned int *crt2y,
811	   unsigned int *crt2clk)
812{
813    SISPtr pSiS = SISPTR(pScrn);
814    DisplayModePtr mode, tmode;
815
816    if(!pSiS->MergedFB) {
817       *pos = SDC_MMODE_POS_ERROR;
818       return;
819    }
820
821    /* Find mode with given timing */
822    mode = sisFindModeFromTiming(pScrn, hd, vd, ht, vt, hss, hse, vss, vse, clk);
823    if(!mode) {
824       *pos = SDC_MMODE_POS_ERROR;
825       return;
826    }
827
828    switch(((SiSMergedDisplayModePtr)mode->Private)->CRT2Position) {
829       case sisLeftOf:  *pos = SDC_MMODE_POS_LEFTOF;  break;
830       case sisRightOf: *pos = SDC_MMODE_POS_RIGHTOF; break;
831       case sisAbove:   *pos = SDC_MMODE_POS_ABOVE;   break;
832       case sisBelow:   *pos = SDC_MMODE_POS_BELOW;   break;
833       default:         *pos = SDC_MMODE_POS_CLONE;
834    }
835
836    tmode = ((SiSMergedDisplayModePtr)mode->Private)->CRT1;
837    *crt1x = tmode->HDisplay;
838    *crt1y = tmode->VDisplay;
839    *crt1clk = (unsigned int)SiSCalcVRate(tmode);
840
841    tmode = ((SiSMergedDisplayModePtr)mode->Private)->CRT2;
842    *crt2x = tmode->HDisplay;
843    *crt2y = tmode->VDisplay;
844    *crt2clk = (unsigned int)SiSCalcVRate(tmode);
845}
846#endif
847
848/***********************************
849 *   SiSCtrl extension interface   *
850 ***********************************/
851
852static void
853sisutil_prepare_string(xSiSCtrlCommandReply *sdcbuf, const char *mystring)
854{
855   int slen = 0;
856   sdcbuf->sdc_buffer[0] = 0;
857   if(mystring) {
858      slen = strlen(mystring);
859      if(slen > 31) slen = 31;
860      strncpy(&sdcbuf->sdc_buffer[0], mystring, slen);
861      sdcbuf->sdc_buffer[slen] = 0;
862   }
863   sdcbuf->sdc_result[0] = slen;
864}
865
866static int
867SiSHandleSiSDirectCommand(xSiSCtrlCommandReply *sdcbuf)
868{
869   ScrnInfoPtr pScrn = xf86ScreenToScrn(screenInfo.screens[sdcbuf->screen]);
870   SISPtr pSiS = SISPTR(pScrn);
871#ifdef SISDUALHEAD
872   SISEntPtr pSiSEnt = pSiS->entityPrivate;
873#endif
874   SISPortPrivPtr pPriv = NULL;
875   int i;
876   ULong j;
877
878   if(sdcbuf->sdc_id != SDC_ID) return BadMatch;
879
880   if(pSiS->adaptor) {
881      pPriv = GET_PORT_PRIVATE(pScrn);
882   }
883
884   j = sdcbuf->sdc_command;
885   for(i = 0; i < SDC_NUM_PARM_RESULT; i++) {
886      j += sdcbuf->sdc_parm[i];
887   }
888
889   if(j != sdcbuf->sdc_chksum) return BadMatch;
890
891   sdcbuf->sdc_result_header = SDC_RESULT_OK;
892
893   switch(sdcbuf->sdc_command) {
894
895   case SDC_CMD_GETVERSION:
896      sdcbuf->sdc_result[0] = SDC_VERSION;
897      sdcbuf->sdc_result[1] = SDC_MAXCOMMAND;
898      break;
899
900   case SDC_CMD_GETHWINFO:
901      {
902	 UShort romptr = 0;
903	 char *biosvers = NULL;
904	 int slen = 0;
905
906	 if(pSiS->BIOS) {
907	    romptr = pSiS->BIOS[0x16] | (pSiS->BIOS[0x17] << 8);
908	    if(romptr < 65530) {
909	       biosvers = (char *)&pSiS->BIOS[romptr];
910	       slen = strlen(biosvers);
911	       if(slen > 10) slen = 10;
912	    }
913	 }
914	 sdcbuf->sdc_result[0]  = pSiS->IsAGPCard ? SDC_BUS_TYPE_AGP : SDC_BUS_TYPE_PCI;
915	 if(pSiS->IsPCIExpress) sdcbuf->sdc_result[0] = SDC_BUS_TYPE_PCIE;
916	 sdcbuf->sdc_result[1]  = pSiS->PciBus;
917	 sdcbuf->sdc_result[2]  = pSiS->PciDevice;
918	 sdcbuf->sdc_result[3]  = pSiS->PciFunc;
919	 sdcbuf->sdc_result[4]  = pSiS->ROM661New ? 1 : (pSiS->HaveXGIBIOS ? 2 : 0),
920	 sdcbuf->sdc_result[5]  = pSiS->ChipFlags;
921	 sdcbuf->sdc_result[6]  = pSiS->ChipType;
922	 sdcbuf->sdc_result[7]  = pSiS->ChipRev;
923	 sdcbuf->sdc_result[8]  = SISDRIVERVERSIONYEAR;
924	 sdcbuf->sdc_result[9]  = SISDRIVERVERSIONMONTH;
925	 sdcbuf->sdc_result[10] = SISDRIVERVERSIONDAY;
926	 sdcbuf->sdc_result[11] = SISDRIVERREVISION;
927	 sdcbuf->sdc_result[12] = pScrn->videoRam;
928	 sdcbuf->sdc_result[13] = pSiS->UMAsize;
929	 sdcbuf->sdc_result[14] = pSiS->LFBsize;
930	 if(slen) strncpy(&sdcbuf->sdc_buffer[0], biosvers, slen);
931	 sdcbuf->sdc_buffer[slen] = 0;
932      }
933      break;
934
935   case SDC_CMD_GETALLFLAGS:
936      sdcbuf->sdc_result[0] = SIS_VBFlagsVersion;
937      sdcbuf->sdc_result[1] = pSiS->VBFlags;
938      sdcbuf->sdc_result[2] = pSiS->SiS_SD_Flags;
939      sdcbuf->sdc_result[3] = pSiS->SiS_SD2_Flags;
940      sdcbuf->sdc_result[4] = pSiS->detectedCRT2Devices;
941      sdcbuf->sdc_result[5] = pSiS->VBFlags2;
942      sdcbuf->sdc_result[6] = pSiS->SiS_SD3_Flags;
943      sdcbuf->sdc_result[7] = pSiS->SiS_SD4_Flags;
944      sdcbuf->sdc_result[8] = pSiS->VBFlags3;
945      sdcbuf->sdc_result[9] = pSiS->VBFlags4;
946      break;
947
948   case SDC_CMD_GETVBFLAGSVERSION:
949      sdcbuf->sdc_result[0] = SIS_VBFlagsVersion;
950      break;
951
952   case SDC_CMD_GETVBFLAGS:
953      sdcbuf->sdc_result[0] = pSiS->VBFlags;
954      sdcbuf->sdc_result[1] = pSiS->VBFlags2;
955      sdcbuf->sdc_result[2] = pSiS->VBFlags3;
956      sdcbuf->sdc_result[3] = pSiS->VBFlags4;
957      break;
958
959   case SDC_CMD_CHECKMODEFORCRT2:
960      {
961	 int clk, hd, hss, hse, ht, vd, vss, vse, vt, result;
962	 ULong flags;
963
964	 flags = sdcbuf->sdc_parm[0];
965	 clk   = sdcbuf->sdc_parm[1];
966	 hd    = sdcbuf->sdc_parm[2];
967	 hss   = sdcbuf->sdc_parm[3];
968	 hse   = sdcbuf->sdc_parm[4];
969	 ht    = sdcbuf->sdc_parm[5];
970	 vd    = sdcbuf->sdc_parm[6];
971	 vss   = sdcbuf->sdc_parm[7];
972	 vse   = sdcbuf->sdc_parm[8];
973	 vt    = sdcbuf->sdc_parm[9];
974
975	 result = SISCheckModeTimingForCRT2Type(pScrn, (UShort)(flags & 0xff),
976			hd, vd, ht, vt, hss, hse, vss, vse, clk, pSiS->SCLogQuiet) & 0xff;
977	 sdcbuf->sdc_result[0] = result;
978      }
979      break;
980
981   case SDC_CMD_SETVBFLAGS:
982#ifdef SISDUALHEAD
983      if(!pSiS->DualHeadMode) {
984#endif
985	 if(pSiS->xv_sisdirectunlocked) {
986	    SISSwitchCRT2Type(pScrn, (ULong)sdcbuf->sdc_parm[0], pSiS->SCLogQuiet);
987	    if(pPriv) SISUpdateVideoParms(pSiS, pPriv);
988	 } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
989#ifdef SISDUALHEAD
990      } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
991#endif
992      break;
993
994   case SDC_CMD_NEWSETVBFLAGS:
995#ifdef SISDUALHEAD
996      if(!pSiS->DualHeadMode) {
997#endif
998	 if(pSiS->xv_sisdirectunlocked) {
999	    SISSwitchOutputType(pScrn, (ULong)sdcbuf->sdc_parm[0], (ULong)sdcbuf->sdc_parm[1],
1000	    		(ULong)sdcbuf->sdc_parm[2], pSiS->SCLogQuiet);
1001	    if(pPriv) SISUpdateVideoParms(pSiS, pPriv);
1002	 } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
1003#ifdef SISDUALHEAD
1004      } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
1005#endif
1006      break;
1007
1008   case SDC_CMD_GETDETECTEDDEVICES:
1009      sdcbuf->sdc_result[0] = pSiS->detectedCRT2Devices;
1010      break;
1011
1012   case SDC_CMD_REDETECTCRT2DEVICES:
1013#ifdef SISDUALHEAD
1014      if(!pSiS->DualHeadMode) {
1015#endif
1016	 if(pSiS->xv_sisdirectunlocked) {
1017	    SISRedetectCRT2Devices(pScrn);
1018	 } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
1019#ifdef SISDUALHEAD
1020      } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
1021#endif
1022      break;
1023
1024   case SDC_CMD_GETCRT1STATUS:
1025      sdcbuf->sdc_result[0] = pSiS->CRT1isoff ? 0 : 1;
1026      break;
1027
1028   case SDC_CMD_SETCRT1STATUS:
1029#ifdef SISDUALHEAD
1030      if(!pSiS->DualHeadMode) {
1031#endif
1032	 if(pSiS->xv_sisdirectunlocked) {
1033	    SISSwitchCRT1Status(pScrn, (ULong)sdcbuf->sdc_parm[0], pSiS->SCLogQuiet);
1034	    if(pPriv) SISUpdateVideoParms(pSiS, pPriv);
1035	 } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
1036#ifdef SISDUALHEAD
1037      } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
1038#endif
1039      break;
1040
1041   case SDC_CMD_GETSDFLAGS:
1042      sdcbuf->sdc_result[0] = pSiS->SiS_SD_Flags;
1043      break;
1044
1045   case SDC_CMD_GETSD2FLAGS:
1046      sdcbuf->sdc_result[0] = pSiS->SiS_SD2_Flags;
1047      break;
1048
1049   case SDC_CMD_GETLOCKSTATUS:
1050      sdcbuf->sdc_result[0] = pSiS->xv_sisdirectunlocked;
1051      break;
1052
1053   case SDC_CMD_SETLOCKSTATUS:
1054      if(pSiS->enablesisctrl) {
1055	 if(sdcbuf->sdc_parm[0] == SIS_DIRECTKEY) {
1056	    pSiS->xv_sisdirectunlocked++;
1057	 } else if(pSiS->xv_sisdirectunlocked) {
1058	    pSiS->xv_sisdirectunlocked--;
1059	 }
1060      } else {
1061	 pSiS->xv_sisdirectunlocked = 0;
1062	 sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
1063      }
1064      break;
1065
1066   case SDC_CMD_GETTVANTIFLICKER:
1067      sdcbuf->sdc_result[0] = SiS_GetSISTVantiflicker(pScrn);
1068      break;
1069
1070   case SDC_CMD_SETTVANTIFLICKER:
1071      if(pSiS->xv_sisdirectunlocked) {
1072	 SiS_SetSISTVantiflicker(pScrn, (int)sdcbuf->sdc_parm[0]);
1073      } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
1074      break;
1075
1076   case SDC_CMD_GETTVSATURATION:
1077      sdcbuf->sdc_result[0] = SiS_GetSISTVsaturation(pScrn);
1078      break;
1079
1080   case SDC_CMD_SETTVSATURATION:
1081      if(pSiS->xv_sisdirectunlocked) {
1082	 SiS_SetSISTVsaturation(pScrn, (int)sdcbuf->sdc_parm[0]);
1083      } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
1084      break;
1085
1086   case SDC_CMD_GETTVEDGEENHANCE:
1087      sdcbuf->sdc_result[0] = SiS_GetSISTVedgeenhance(pScrn);;
1088      break;
1089
1090   case SDC_CMD_SETTVEDGEENHANCE:
1091      if(pSiS->xv_sisdirectunlocked) {
1092	 SiS_SetSISTVedgeenhance(pScrn, (int)sdcbuf->sdc_parm[0]);
1093      } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
1094      break;
1095
1096   case SDC_CMD_GETTVCFILTER:
1097      sdcbuf->sdc_result[0] = SiS_GetSISTVcfilter(pScrn);
1098      break;
1099
1100   case SDC_CMD_SETTVCFILTER:
1101      if(pSiS->xv_sisdirectunlocked) {
1102	 SiS_SetSISTVcfilter(pScrn, sdcbuf->sdc_parm[0] ? 1 : 0);
1103      } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
1104      break;
1105
1106   case SDC_CMD_GETTVYFILTER:
1107      sdcbuf->sdc_result[0] = SiS_GetSISTVyfilter(pScrn);
1108      break;
1109
1110   case SDC_CMD_SETTVYFILTER:
1111      if(pSiS->xv_sisdirectunlocked) {
1112	 SiS_SetSISTVyfilter(pScrn, sdcbuf->sdc_parm[0]);
1113      } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
1114      break;
1115
1116   case SDC_CMD_GETTVCOLORCALIB:
1117      sdcbuf->sdc_result[0] = SiS_GetSISTVcolcalib(pScrn, TRUE) + 32768;
1118      sdcbuf->sdc_result[1] = SiS_GetSISTVcolcalib(pScrn, FALSE) + 32768;
1119      break;
1120
1121   case SDC_CMD_SETTVCOLORCALIB:
1122      if(pSiS->xv_sisdirectunlocked) {
1123         SiS_SetSISTVcolcalib(pScrn, (int)sdcbuf->sdc_parm[0] - 32768, TRUE);
1124	 SiS_SetSISTVcolcalib(pScrn, (int)sdcbuf->sdc_parm[1] - 32768, FALSE);
1125      } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
1126      break;
1127
1128   case SDC_CMD_GETTVCHCONTRAST:
1129      sdcbuf->sdc_result[0] = SiS_GetCHTVcontrast(pScrn);
1130      break;
1131
1132   case SDC_CMD_SETTVCHCONTRAST:
1133      if(pSiS->xv_sisdirectunlocked) {
1134	 SiS_SetCHTVcontrast(pScrn, (int)sdcbuf->sdc_parm[0]);
1135      } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
1136      break;
1137
1138   case SDC_CMD_GETTVCHTEXTENHANCE:
1139      sdcbuf->sdc_result[0] = SiS_GetCHTVtextenhance(pScrn);
1140      break;
1141
1142   case SDC_CMD_SETTVCHTEXTENHANCE:
1143      if(pSiS->xv_sisdirectunlocked) {
1144	 SiS_SetCHTVtextenhance(pScrn, (int)sdcbuf->sdc_parm[0]);
1145      } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
1146      break;
1147
1148   case SDC_CMD_GETTVCHCHROMAFLICKERFILTER:
1149      sdcbuf->sdc_result[0] = SiS_GetCHTVchromaflickerfilter(pScrn);
1150      break;
1151
1152   case SDC_CMD_SETTVCHCHROMAFLICKERFILTER:
1153      if(pSiS->xv_sisdirectunlocked) {
1154	 SiS_SetCHTVchromaflickerfilter(pScrn, (int)sdcbuf->sdc_parm[0]);
1155      } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
1156      break;
1157
1158   case SDC_CMD_GETTVCHLUMAFLICKERFILTER:
1159      sdcbuf->sdc_result[0] = SiS_GetCHTVlumaflickerfilter(pScrn);
1160      break;
1161
1162   case SDC_CMD_SETTVCHLUMAFLICKERFILTER:
1163      if(pSiS->xv_sisdirectunlocked) {
1164	 SiS_SetCHTVlumaflickerfilter(pScrn, (int)sdcbuf->sdc_parm[0]);
1165      } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
1166      break;
1167
1168   case SDC_CMD_GETTVCHCVBSCOLOR:
1169      sdcbuf->sdc_result[0] = SiS_GetCHTVcvbscolor(pScrn);
1170      break;
1171
1172   case SDC_CMD_SETTVCHCVBSCOLOR:
1173      if(pSiS->xv_sisdirectunlocked) {
1174	 SiS_SetCHTVcvbscolor(pScrn, sdcbuf->sdc_parm[0] ? 1 : 0);
1175      } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
1176      break;
1177
1178   case SDC_CMD_GETCHTVOVERSCAN:
1179      {  /* Changing of CRT2 settings not supported in DHM! */
1180	 int i = 0;
1181	 if(pSiS->OptTVSOver == 1)         i = 3;
1182	 else if(pSiS->UseCHOverScan == 1) i = 2;
1183	 else if(pSiS->UseCHOverScan == 0) i = 1;
1184	 sdcbuf->sdc_result[0] = i;
1185      }
1186      break;
1187
1188   case SDC_CMD_SETCHTVOVERSCAN:
1189      if(pSiS->xv_sisdirectunlocked) {
1190	 pSiS->UseCHOverScan = -1;
1191	 pSiS->OptTVSOver = FALSE;
1192	 if(sdcbuf->sdc_parm[0] == 3) {
1193	    if(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTSOVER) {
1194	       pSiS->OptTVSOver = TRUE;
1195	    }
1196	    pSiS->UseCHOverScan = 1;
1197	 } else if(sdcbuf->sdc_parm[0] == 2) pSiS->UseCHOverScan = 1;
1198	 else if(sdcbuf->sdc_parm[0] == 1)   pSiS->UseCHOverScan = 0;
1199      } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
1200      break;
1201
1202   case SDC_CMD_GETGAMMASTATUS:
1203      {
1204         int i = 0;
1205#ifdef SISDUALHEAD
1206	 if(pSiS->DualHeadMode) {
1207	    if(pSiSEnt->CRT1gamma) i |= 0x01;
1208	    if(pSiSEnt->CRT2gamma) i |= 0x02;
1209	 } else {
1210#endif
1211	    if(pSiS->CRT1gamma)    i |= 0x01;
1212	    if(pSiS->CRT2gamma)    i |= 0x02;
1213	    if(pSiS->CRT2SepGamma) i |= 0x08;
1214#ifdef SISDUALHEAD
1215	 }
1216#endif
1217	 if(pSiS->XvGamma) i |= 0x04;
1218         sdcbuf->sdc_result[0] = i;
1219      }
1220      break;
1221
1222   case SDC_CMD_SETGAMMASTATUS:
1223      if(pSiS->xv_sisdirectunlocked) {
1224         int value = sdcbuf->sdc_parm[0];
1225	 Bool backup = pSiS->XvGamma;
1226	 Bool backup2 = pSiS->CRT2SepGamma;
1227	 pSiS->CRT1gamma = (value & 0x01) ? TRUE : FALSE;
1228	 pSiS->CRT2gamma = (value & 0x02) ? TRUE : FALSE;
1229#ifdef SISDUALHEAD
1230	 if(pSiS->DualHeadMode) {
1231	    pSiSEnt->CRT1gamma = pSiS->CRT1gamma;
1232	    pSiSEnt->CRT2gamma = pSiS->CRT2gamma;
1233	 }
1234#endif
1235	 if(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTSGRCRT2) {
1236	    pSiS->CRT2SepGamma = (value & 0x08) ? TRUE : FALSE;
1237	    if(pSiS->CRT2SepGamma != backup2) {
1238	       if(pSiS->CRT2SepGamma) {
1239		  SiS_UpdateGammaCRT2(pScrn);
1240	       }
1241#ifdef SISGAMMARAMP
1242	       else {
1243		  SISCalculateGammaRamp(pScrn->pScreen, pScrn);
1244	       }
1245#endif
1246	      /* ATTN: When disabling CRT2 sep gamma,
1247	       * as long as SISGAMMARAMP is not defined,
1248	       * application needs to reset palette using
1249	       * vidmodextension! (See SiS_SD_CANSETGAMMA)
1250	       *
1251	       * Note: Difference between setting gamma values
1252	       * for CRT1 and CRT2: For CRT1, driver only
1253	       * stores the values, but does nothing with them;
1254	       * App needs to calc gamma ramp itself for CRT1,
1255	       * and set it using the VidModExtention.
1256	       * For CRT2, the driver will IMMEDIATELY recalc
1257	       * the palette.
1258	       */
1259	    }
1260	 } else pSiS->CRT2SepGamma = FALSE;
1261
1262	 pSiS->XvGamma = (value & 0x04) ? TRUE : FALSE;
1263	 if(pSiS->VGAEngine == SIS_315_VGA) {
1264	    if(backup != pSiS->XvGamma) {
1265	       if(pPriv) SiSUpdateXvGamma(pSiS, pPriv);
1266	    }
1267	 }
1268      } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
1269      break;
1270
1271   case SDC_CMD_GETTVXSCALE:
1272      sdcbuf->sdc_result[0] = SiS_GetTVxscale(pScrn) + 32768;
1273      break;
1274
1275   case SDC_CMD_SETTVXSCALE:
1276      {
1277         int value = sdcbuf->sdc_parm[0] - 32768;
1278         if((value < -16) || (value > 16)) {
1279	    sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
1280         } else if(pSiS->xv_sisdirectunlocked) {
1281	    SiS_SetTVxscale(pScrn, value);
1282         } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
1283      }
1284      break;
1285
1286   case SDC_CMD_GETTVYSCALE:
1287      sdcbuf->sdc_result[0] = SiS_GetTVyscale(pScrn) + 32768;
1288      break;
1289
1290   case SDC_CMD_SETTVYSCALE:
1291      {
1292         int value = sdcbuf->sdc_parm[0] - 32768;
1293         if((value < -4) || (value > 3)) {
1294	    sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
1295         } else if(pSiS->xv_sisdirectunlocked) {
1296	    SiS_SetTVyscale(pScrn, value);
1297         } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
1298      }
1299      break;
1300
1301   case SDC_CMD_GETSCREENSIZE:
1302      sdcbuf->sdc_result[0] = (pScrn->virtualX << 16) | pScrn->virtualY;
1303      break;
1304
1305   case SDC_CMD_GETGAMMABRIGHTNESS:  /* xv_BRx, xv_PBx */
1306      sdcbuf->sdc_result[0] = pSiS->GammaBriR;
1307      sdcbuf->sdc_result[1] = pSiS->GammaBriG;
1308      sdcbuf->sdc_result[2] = pSiS->GammaBriB;
1309      break;
1310
1311   case SDC_CMD_GETNEWGAMMABRICON:  /* no xv pendant */
1312      sdcbuf->sdc_result[0] = (CARD32)(((int)(pSiS->NewGammaBriR * 1000.0)) + 1000);
1313      sdcbuf->sdc_result[1] = (CARD32)(((int)(pSiS->NewGammaBriG * 1000.0)) + 1000);
1314      sdcbuf->sdc_result[2] = (CARD32)(((int)(pSiS->NewGammaBriB * 1000.0)) + 1000);
1315      sdcbuf->sdc_result[3] = (CARD32)(((int)(pSiS->NewGammaConR * 1000.0)) + 1000);
1316      sdcbuf->sdc_result[4] = (CARD32)(((int)(pSiS->NewGammaConG * 1000.0)) + 1000);
1317      sdcbuf->sdc_result[5] = (CARD32)(((int)(pSiS->NewGammaConB * 1000.0)) + 1000);
1318      break;
1319
1320   case SDC_CMD_SETGAMMABRIGHTNESS:  /* xv_BRx, xv_PBx */
1321      if(sdcbuf->sdc_parm[0] < 100 || sdcbuf->sdc_parm[0] > 10000 ||
1322	 sdcbuf->sdc_parm[1] < 100 || sdcbuf->sdc_parm[1] > 10000 ||
1323	 sdcbuf->sdc_parm[2] < 100 || sdcbuf->sdc_parm[2] > 10000) {
1324	 sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
1325      } else if(pSiS->xv_sisdirectunlocked) {
1326	 pSiS->GammaBriR = sdcbuf->sdc_parm[0];
1327	 pSiS->GammaBriG = sdcbuf->sdc_parm[1];
1328	 pSiS->GammaBriB = sdcbuf->sdc_parm[2];
1329	 pSiS->NewGammaBriR = pSiS->NewGammaBriG = pSiS->NewGammaBriB = 0.0;
1330	 pSiS->NewGammaConR = pSiS->NewGammaConG = pSiS->NewGammaConB = 0.0;
1331	 pSiS->SiS_SD3_Flags |= SiS_SD3_OLDGAMMAINUSE;
1332      } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
1333      break;
1334
1335   case SDC_CMD_SETNEWGAMMABRICON:  /* no xv pendant */
1336      if(sdcbuf->sdc_parm[0] > 2000 || sdcbuf->sdc_parm[1] > 2000 ||
1337	 sdcbuf->sdc_parm[2] > 2000 || sdcbuf->sdc_parm[3] > 2000 ||
1338	 sdcbuf->sdc_parm[4] > 2000 || sdcbuf->sdc_parm[5] > 2000) {
1339	 sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
1340      } else if(pSiS->xv_sisdirectunlocked) {
1341	 pSiS->NewGammaBriR = ((float)((int)sdcbuf->sdc_parm[0] - 1000)) / 1000.0;
1342	 pSiS->NewGammaBriG = ((float)((int)sdcbuf->sdc_parm[1] - 1000)) / 1000.0;
1343	 pSiS->NewGammaBriB = ((float)((int)sdcbuf->sdc_parm[2] - 1000)) / 1000.0;
1344	 pSiS->NewGammaConR = ((float)((int)sdcbuf->sdc_parm[3] - 1000)) / 1000.0;
1345	 pSiS->NewGammaConG = ((float)((int)sdcbuf->sdc_parm[4] - 1000)) / 1000.0;
1346	 pSiS->NewGammaConB = ((float)((int)sdcbuf->sdc_parm[5] - 1000)) / 1000.0;
1347	 pSiS->GammaBriR = pSiS->GammaBriG = pSiS->GammaBriB = 1000;
1348	 pSiS->SiS_SD3_Flags &= ~SiS_SD3_OLDGAMMAINUSE;
1349      } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
1350      break;
1351
1352   case SDC_CMD_GETGAMMABRIGHTNESS2: /* xv_BRx2, xv_PBx2 */
1353#ifdef SISDUALHEAD
1354      if(pSiS->DualHeadMode) {
1355         sdcbuf->sdc_result[0] = pSiSEnt->GammaBriR;
1356	 sdcbuf->sdc_result[1] = pSiSEnt->GammaBriG;
1357	 sdcbuf->sdc_result[2] = pSiSEnt->GammaBriB;
1358	 break;
1359      }
1360#endif
1361      sdcbuf->sdc_result[0] = pSiS->GammaBriR;
1362      sdcbuf->sdc_result[1] = pSiS->GammaBriG;
1363      sdcbuf->sdc_result[2] = pSiS->GammaBriB;
1364      break;
1365
1366   case SDC_CMD_GETNEWGAMMABRICON2: /* no xv pendant */
1367#ifdef SISDUALHEAD
1368      if(pSiS->DualHeadMode) {
1369         sdcbuf->sdc_result[0] = (CARD32)(((int)(pSiSEnt->NewGammaBriR * 1000.0)) + 1000);
1370	 sdcbuf->sdc_result[1] = (CARD32)(((int)(pSiSEnt->NewGammaBriG * 1000.0)) + 1000);
1371	 sdcbuf->sdc_result[2] = (CARD32)(((int)(pSiSEnt->NewGammaBriB * 1000.0)) + 1000);
1372	 sdcbuf->sdc_result[3] = (CARD32)(((int)(pSiSEnt->NewGammaConR * 1000.0)) + 1000);
1373	 sdcbuf->sdc_result[4] = (CARD32)(((int)(pSiSEnt->NewGammaConG * 1000.0)) + 1000);
1374	 sdcbuf->sdc_result[5] = (CARD32)(((int)(pSiSEnt->NewGammaConB * 1000.0)) + 1000);
1375	 break;
1376      }
1377#endif
1378      sdcbuf->sdc_result[0] = (CARD32)(((int)(pSiS->NewGammaBriR * 1000.0)) + 1000);
1379      sdcbuf->sdc_result[1] = (CARD32)(((int)(pSiS->NewGammaBriG * 1000.0)) + 1000);
1380      sdcbuf->sdc_result[2] = (CARD32)(((int)(pSiS->NewGammaBriB * 1000.0)) + 1000);
1381      sdcbuf->sdc_result[3] = (CARD32)(((int)(pSiS->NewGammaConR * 1000.0)) + 1000);
1382      sdcbuf->sdc_result[4] = (CARD32)(((int)(pSiS->NewGammaConG * 1000.0)) + 1000);
1383      sdcbuf->sdc_result[5] = (CARD32)(((int)(pSiS->NewGammaConB * 1000.0)) + 1000);
1384      break;
1385
1386   case SDC_CMD_SETGAMMABRIGHTNESS2: /* xv_BRx2, xv_PBx2 */
1387      if(sdcbuf->sdc_parm[0] < 100 || sdcbuf->sdc_parm[0] > 10000 ||
1388	 sdcbuf->sdc_parm[1] < 100 || sdcbuf->sdc_parm[1] > 10000 ||
1389	 sdcbuf->sdc_parm[2] < 100 || sdcbuf->sdc_parm[2] > 10000) {
1390	 sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
1391      } else if(pSiS->xv_sisdirectunlocked) {
1392         pSiS->SiS_SD3_Flags |= SiS_SD3_OLDGAMMAINUSE;
1393#ifdef SISDUALHEAD
1394	 if(pSiS->DualHeadMode) {
1395	    pSiSEnt->GammaBriR = sdcbuf->sdc_parm[0];
1396	    pSiSEnt->GammaBriG = sdcbuf->sdc_parm[1];
1397	    pSiSEnt->GammaBriB = sdcbuf->sdc_parm[2];
1398	    pSiSEnt->NewGammaBriR = pSiSEnt->NewGammaBriG = pSiSEnt->NewGammaBriB = 0.0;
1399	    pSiSEnt->NewGammaConR = pSiSEnt->NewGammaConG = pSiSEnt->NewGammaConB = 0.0;
1400	 }
1401#endif
1402      } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
1403      break;
1404
1405   case SDC_CMD_SETNEWGAMMABRICON2: /* no xv pendant */
1406      if(sdcbuf->sdc_parm[0] > 2000 || sdcbuf->sdc_parm[1] > 2000 ||
1407	 sdcbuf->sdc_parm[2] > 2000 || sdcbuf->sdc_parm[3] > 2000 ||
1408	 sdcbuf->sdc_parm[4] > 2000 || sdcbuf->sdc_parm[5] > 2000) {
1409	 sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
1410      } else if(pSiS->xv_sisdirectunlocked) {
1411         pSiS->SiS_SD3_Flags &= ~SiS_SD3_OLDGAMMAINUSE;
1412#ifdef SISDUALHEAD
1413	 if(pSiS->DualHeadMode) {
1414	    pSiSEnt->NewGammaBriR = ((float)((int)sdcbuf->sdc_parm[0] - 1000)) / 1000.0;
1415	    pSiSEnt->NewGammaBriG = ((float)((int)sdcbuf->sdc_parm[1] - 1000)) / 1000.0;
1416	    pSiSEnt->NewGammaBriB = ((float)((int)sdcbuf->sdc_parm[2] - 1000)) / 1000.0;
1417	    pSiSEnt->NewGammaConR = ((float)((int)sdcbuf->sdc_parm[3] - 1000)) / 1000.0;
1418	    pSiSEnt->NewGammaConG = ((float)((int)sdcbuf->sdc_parm[4] - 1000)) / 1000.0;
1419	    pSiSEnt->NewGammaConB = ((float)((int)sdcbuf->sdc_parm[5] - 1000)) / 1000.0;
1420	    pSiSEnt->GammaBriR = pSiSEnt->GammaBriG = pSiSEnt->GammaBriB = 1000;
1421	 }
1422#endif
1423      } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
1424      break;
1425
1426   case SDC_CMD_GETGETGAMMACRT2:
1427      sdcbuf->sdc_result[0] = (ULong)(pSiS->GammaR2 * 1000);
1428      sdcbuf->sdc_result[1] = (ULong)(pSiS->GammaG2 * 1000);
1429      sdcbuf->sdc_result[2] = (ULong)(pSiS->GammaB2 * 1000);
1430      sdcbuf->sdc_result[3] = pSiS->GammaBriR2;
1431      sdcbuf->sdc_result[4] = pSiS->GammaBriG2;
1432      sdcbuf->sdc_result[5] = pSiS->GammaBriB2;
1433      break;
1434
1435   case SDC_CMD_GETGETNEWGAMMACRT2:
1436      sdcbuf->sdc_result[0] = (ULong)(pSiS->GammaR2 * 1000);
1437      sdcbuf->sdc_result[1] = (ULong)(pSiS->GammaG2 * 1000);
1438      sdcbuf->sdc_result[2] = (ULong)(pSiS->GammaB2 * 1000);
1439      sdcbuf->sdc_result[3] = (CARD32)(((int)(pSiS->NewGammaBriR2 * 1000.0)) + 1000);
1440      sdcbuf->sdc_result[4] = (CARD32)(((int)(pSiS->NewGammaBriG2 * 1000.0)) + 1000);
1441      sdcbuf->sdc_result[5] = (CARD32)(((int)(pSiS->NewGammaBriB2 * 1000.0)) + 1000);
1442      sdcbuf->sdc_result[6] = (CARD32)(((int)(pSiS->NewGammaConR2 * 1000.0)) + 1000);
1443      sdcbuf->sdc_result[7] = (CARD32)(((int)(pSiS->NewGammaConG2 * 1000.0)) + 1000);
1444      sdcbuf->sdc_result[8] = (CARD32)(((int)(pSiS->NewGammaConB2 * 1000.0)) + 1000);
1445      break;
1446
1447   case SDC_CMD_SETGETGAMMACRT2:
1448      if(sdcbuf->sdc_parm[0] < 100 || sdcbuf->sdc_parm[0] > 10000 ||
1449	 sdcbuf->sdc_parm[1] < 100 || sdcbuf->sdc_parm[1] > 10000 ||
1450	 sdcbuf->sdc_parm[2] < 100 || sdcbuf->sdc_parm[2] > 10000 ||
1451	 sdcbuf->sdc_parm[3] < 100 || sdcbuf->sdc_parm[3] > 10000 ||
1452	 sdcbuf->sdc_parm[4] < 100 || sdcbuf->sdc_parm[4] > 10000 ||
1453	 sdcbuf->sdc_parm[5] < 100 || sdcbuf->sdc_parm[5] > 10000) {
1454	 sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
1455      } else if(pSiS->xv_sisdirectunlocked) {
1456         pSiS->GammaR2 = (float)sdcbuf->sdc_parm[0] / (float)1000;
1457	 pSiS->GammaG2 = (float)sdcbuf->sdc_parm[1] / (float)1000;
1458	 pSiS->GammaB2 = (float)sdcbuf->sdc_parm[2] / (float)1000;
1459	 pSiS->GammaBriR2 = sdcbuf->sdc_parm[3];
1460	 pSiS->GammaBriG2 = sdcbuf->sdc_parm[4];
1461	 pSiS->GammaBriB2 = sdcbuf->sdc_parm[5];
1462	 pSiS->NewGammaBriR2 = pSiS->NewGammaBriG2 = pSiS->NewGammaBriB2 = 0.0;
1463	 pSiS->NewGammaConR2 = pSiS->NewGammaConG2 = pSiS->NewGammaConB2 = 0.0;
1464	 pSiS->SiS_SD3_Flags |= SiS_SD3_OLDGAMMAINUSE;
1465	 SiS_UpdateGammaCRT2(pScrn);
1466      } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
1467      break;
1468
1469   case SDC_CMD_SETGETNEWGAMMACRT2:
1470      if(sdcbuf->sdc_parm[0] < 100 || sdcbuf->sdc_parm[0] > 10000 ||
1471	 sdcbuf->sdc_parm[1] < 100 || sdcbuf->sdc_parm[1] > 10000 ||
1472	 sdcbuf->sdc_parm[2] < 100 || sdcbuf->sdc_parm[2] > 10000 ||
1473	 sdcbuf->sdc_parm[3] > 2000 || sdcbuf->sdc_parm[4] > 2000 ||
1474	 sdcbuf->sdc_parm[5] > 2000 || sdcbuf->sdc_parm[6] > 2000 ||
1475	 sdcbuf->sdc_parm[7] > 2000 || sdcbuf->sdc_parm[8] > 2000) {
1476	 sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
1477      } else if(pSiS->xv_sisdirectunlocked) {
1478         pSiS->GammaR2 = (float)sdcbuf->sdc_parm[0] / (float)1000;
1479	 pSiS->GammaG2 = (float)sdcbuf->sdc_parm[1] / (float)1000;
1480	 pSiS->GammaB2 = (float)sdcbuf->sdc_parm[2] / (float)1000;
1481	 pSiS->NewGammaBriR2 = ((float)((int)sdcbuf->sdc_parm[3] - 1000)) / 1000.0;
1482	 pSiS->NewGammaBriG2 = ((float)((int)sdcbuf->sdc_parm[4] - 1000)) / 1000.0;
1483	 pSiS->NewGammaBriB2 = ((float)((int)sdcbuf->sdc_parm[5] - 1000)) / 1000.0;
1484	 pSiS->NewGammaConR2 = ((float)((int)sdcbuf->sdc_parm[6] - 1000)) / 1000.0;
1485	 pSiS->NewGammaConG2 = ((float)((int)sdcbuf->sdc_parm[7] - 1000)) / 1000.0;
1486	 pSiS->NewGammaConB2 = ((float)((int)sdcbuf->sdc_parm[8] - 1000)) / 1000.0;
1487	 pSiS->GammaBriR2 = pSiS->GammaBriG2 = pSiS->GammaBriB2 = 1000;
1488	 pSiS->SiS_SD3_Flags &= ~SiS_SD3_OLDGAMMAINUSE;
1489	 SiS_UpdateGammaCRT2(pScrn);
1490      } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
1491      break;
1492
1493   case SDC_CMD_GETHWCURSORSTATUS:
1494      sdcbuf->sdc_result[0] = pSiS->HideHWCursor ? 1 : 0;
1495      break;
1496
1497   case SDC_CMD_SETHWCURSORSTATUS:
1498      if(pSiS->xv_sisdirectunlocked) {
1499	 Bool VisibleBackup = pSiS->HWCursorIsVisible;
1500	 pSiS->HideHWCursor = sdcbuf->sdc_parm[0] ? TRUE : FALSE;
1501	 if(pSiS->CursorInfoPtr) {
1502	    if(VisibleBackup) {
1503	       if(sdcbuf->sdc_parm[0]) {
1504	 	  (pSiS->CursorInfoPtr->HideCursor)(pScrn);
1505	       } else {
1506		  (pSiS->CursorInfoPtr->ShowCursor)(pScrn);
1507	       }
1508	    }
1509	    pSiS->HWCursorIsVisible = VisibleBackup;
1510	 }
1511      } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
1512      break;
1513
1514   case SDC_CMD_GETPANELMODE:
1515      {
1516	 int i = 0;
1517	 if(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTSCALE) {
1518	    switch(pSiS->SiS_Pr->UsePanelScaler) {
1519	    case -1: i |= 0x01; break;
1520	    case 1:  i |= 0x02; break;
1521	    }
1522	    if(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTCENTER) {
1523	       switch(pSiS->SiS_Pr->CenterScreen) {
1524	       case -1: i |= 0x04; break;
1525	       case 1:  i |= 0x08; break;
1526	       }
1527	    }
1528	 }
1529	 sdcbuf->sdc_result[0] = i;
1530      }
1531      break;
1532
1533   case SDC_CMD_SETPANELMODE:
1534      if(pSiS->xv_sisdirectunlocked) {
1535         int value = sdcbuf->sdc_parm[0];
1536         if(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTSCALE) {
1537	    if(value & 0x01)      pSiS->SiS_Pr->UsePanelScaler = -1;
1538	    else if(value & 0x02) pSiS->SiS_Pr->UsePanelScaler = 1;
1539	    else		  pSiS->SiS_Pr->UsePanelScaler = 0;
1540	    if(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTCENTER) {
1541	       if(value & 0x04)      pSiS->SiS_Pr->CenterScreen = -1;
1542	       else if(value & 0x08) pSiS->SiS_Pr->CenterScreen = 1;
1543	       else		     pSiS->SiS_Pr->CenterScreen = 0;
1544	    }
1545         }
1546      } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
1547      break;
1548
1549   case SDC_CMD_GETMERGEDMODEDETAILS:
1550#ifdef SISMERGED
1551      if(pSiS->MergedFB) {
1552         int clk, hd, hss, hse, ht, vd, vss, vse, vt;
1553	 unsigned int pos, crt1x, crt1y, crt1clk, crt2x, crt2y, crt2clk;
1554
1555	 clk   = sdcbuf->sdc_parm[0];
1556	 hd    = sdcbuf->sdc_parm[1];
1557	 hss   = sdcbuf->sdc_parm[2];
1558	 hse   = sdcbuf->sdc_parm[3];
1559	 ht    = sdcbuf->sdc_parm[4];
1560	 vd    = sdcbuf->sdc_parm[5];
1561	 vss   = sdcbuf->sdc_parm[6];
1562	 vse   = sdcbuf->sdc_parm[7];
1563	 vt    = sdcbuf->sdc_parm[8];
1564
1565	 SISGetMergedModeDetails(pScrn,
1566		hd, vd, ht, vt, hss, hse, vss, vse, clk,
1567		&pos, &crt1x, &crt1y, &crt1clk, &crt2x, &crt2y, &crt2clk);
1568
1569	 sdcbuf->sdc_result[0] = pos;
1570	 sdcbuf->sdc_result[1] = crt1x;
1571	 sdcbuf->sdc_result[2] = crt1y;
1572	 sdcbuf->sdc_result[3] = crt1clk;
1573	 sdcbuf->sdc_result[4] = crt2x;
1574	 sdcbuf->sdc_result[5] = crt2y;
1575	 sdcbuf->sdc_result[6] = crt2clk;
1576
1577	 switch(pSiS->CRT2Position) {
1578	 case sisLeftOf:  sdcbuf->sdc_result[7] = SDC_MMODE_POS_LEFTOF; break;
1579	 case sisRightOf: sdcbuf->sdc_result[7] = SDC_MMODE_POS_RIGHTOF; break;
1580	 case sisAbove:   sdcbuf->sdc_result[7] = SDC_MMODE_POS_ABOVE; break;
1581	 case sisBelow:   sdcbuf->sdc_result[7] = SDC_MMODE_POS_BELOW; break;
1582	 default:         sdcbuf->sdc_result[7] = SDC_MMODE_POS_CLONE;
1583	 }
1584
1585      } else
1586#endif
1587         sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
1588      break;
1589
1590   case SDC_CMD_GETDEVICENAME:		/* In DualHead mode, this returns CRT1 data */
1591      {
1592         SISPtr	mypSiS = pSiS;
1593	 sdcbuf->sdc_result[0] = 0;
1594#ifdef SISDUALHEAD
1595	 if(pSiS->DualHeadMode) {
1596	    if(pSiSEnt->pScrn_2) mypSiS = SISPTR(pSiSEnt->pScrn_2);
1597	 }
1598#endif
1599	 sisutil_prepare_string(sdcbuf, mypSiS->devsectname);
1600      }
1601      break;
1602
1603   case SDC_CMD_GETMONITORNAME:		/* In DualHead mode, this returns CRT1 data */
1604      {
1605         ScrnInfoPtr mypScrn = pScrn;
1606         sdcbuf->sdc_result[0] = 0;
1607#ifdef SISDUALHEAD
1608	 if(pSiS->DualHeadMode) {
1609	    if(pSiSEnt->pScrn_2) mypScrn = pSiSEnt->pScrn_2;
1610	 }
1611#endif
1612         if(mypScrn->monitor) {
1613            sisutil_prepare_string(sdcbuf, mypScrn->monitor->id);
1614         }
1615      }
1616      break;
1617
1618   case SDC_CMD_GETDEVICENAME2:		/* In DualHead mode, this returns CRT2 data */
1619      sdcbuf->sdc_result[0] = 0;
1620#ifdef SISDUALHEAD
1621      if(pSiS->DualHeadMode) {
1622         if(pSiSEnt->pScrn_1) {
1623	    sisutil_prepare_string(sdcbuf, SISPTR(pSiSEnt->pScrn_1)->devsectname);
1624	 }
1625      } else
1626#endif
1627	 sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
1628      break;
1629
1630   case SDC_CMD_GETMONITORNAME2:	/* In DualHead mode, this returns CRT2 data */
1631      sdcbuf->sdc_result[0] = 0;
1632#ifdef SISDUALHEAD
1633      if(pSiS->DualHeadMode) {
1634         if(pSiSEnt->pScrn_1) {
1635	    if(pSiSEnt->pScrn_1->monitor) {
1636               sisutil_prepare_string(sdcbuf, pSiSEnt->pScrn_1->monitor->id);
1637            }
1638	 }
1639      } else
1640#endif
1641	 sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
1642      break;
1643
1644   case SDC_CMD_SETXVBRIGHTNESS:
1645      if(pPriv) {
1646         int val = sdcbuf->sdc_parm[0] - 32768;
1647         if(val >= -128 && val <= 127) pPriv->brightness = val;
1648	 else sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
1649      } else sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
1650      break;
1651
1652   case SDC_CMD_GETXVBRIGHTNESS:
1653      if(pPriv) {
1654         sdcbuf->sdc_result[0] = pPriv->brightness + 32768;
1655      } else sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
1656      break;
1657
1658   case SDC_CMD_SETXVCONTRAST:
1659      if(pPriv) {
1660         int val = sdcbuf->sdc_parm[0] - 32768;
1661         if(val >= 0 && val <= 7) pPriv->contrast = val;
1662	 else sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
1663      } else sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
1664      break;
1665
1666   case SDC_CMD_GETXVCONTRAST:
1667      if(pPriv) {
1668         sdcbuf->sdc_result[0] = pPriv->contrast + 32768;
1669      } else sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
1670      break;
1671
1672   case SDC_CMD_SETXVHUE:
1673      if((pPriv) && (pSiS->SiS_SD2_Flags & SiS_SD2_SUPPORTXVHUESAT)) {
1674         int val = sdcbuf->sdc_parm[0] - 32768;
1675         if(val >= -8 && val <= 7) pPriv->hue = val;
1676	 else sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
1677      } else sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
1678      break;
1679
1680   case SDC_CMD_GETXVHUE:
1681      if((pPriv) && (pSiS->SiS_SD2_Flags & SiS_SD2_SUPPORTXVHUESAT)) {
1682         sdcbuf->sdc_result[0] = pPriv->hue + 32768;
1683      } else sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
1684      break;
1685
1686   case SDC_CMD_SETXVSATURATION:
1687      if((pPriv) && (pSiS->SiS_SD2_Flags & SiS_SD2_SUPPORTXVHUESAT)) {
1688         int val = sdcbuf->sdc_parm[0] - 32768;
1689         if(val >= -7 && val <= 7) pPriv->saturation = val;
1690	 else sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
1691      } else sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
1692      break;
1693
1694   case SDC_CMD_GETXVSATURATION:
1695      if((pPriv) && (pSiS->SiS_SD2_Flags & SiS_SD2_SUPPORTXVHUESAT)) {
1696         sdcbuf->sdc_result[0] = pPriv->saturation + 32768;
1697      } else sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
1698      break;
1699
1700   case SDC_CMD_SETXVGAMMA:
1701      if((pPriv) && (pSiS->SiS_SD_Flags & SiS_SD_SUPPORTXVGAMMA1)) {
1702         if(sdcbuf->sdc_parm[0] < 100 || sdcbuf->sdc_parm[0] > 10000 ||
1703	    sdcbuf->sdc_parm[1] < 100 || sdcbuf->sdc_parm[1] > 10000 ||
1704	    sdcbuf->sdc_parm[2] < 100 || sdcbuf->sdc_parm[2] > 10000) {
1705	    sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
1706	 } else {
1707	    pSiS->XvGammaRed = sdcbuf->sdc_parm[0];
1708	    pSiS->XvGammaGreen = sdcbuf->sdc_parm[1];
1709	    pSiS->XvGammaBlue = sdcbuf->sdc_parm[2];
1710	    SiSUpdateXvGamma(pSiS, pPriv);
1711	 }
1712      } else sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
1713      break;
1714
1715   case SDC_CMD_GETXVGAMMA:
1716      if((pPriv) && (pSiS->SiS_SD_Flags & SiS_SD_SUPPORTXVGAMMA1)) {
1717         sdcbuf->sdc_result[0] = pSiS->XvGammaRed;
1718	 sdcbuf->sdc_result[1] = pSiS->XvGammaGreen;
1719	 sdcbuf->sdc_result[2] = pSiS->XvGammaBlue;
1720      } else sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
1721      break;
1722
1723   case SDC_CMD_SETXVCOLORKEY:
1724      if(pPriv) {
1725         pPriv->colorKey = pSiS->colorKey = sdcbuf->sdc_parm[0];
1726      } else sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
1727      break;
1728
1729   case SDC_CMD_GETXVCOLORKEY:
1730      if(pPriv) {
1731         sdcbuf->sdc_result[0] = pPriv->colorKey;
1732      } else sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
1733      break;
1734
1735   case SDC_CMD_SETXVAUTOPAINTCOLORKEY:
1736      if(pPriv) {
1737         pPriv->autopaintColorKey = sdcbuf->sdc_parm[0] ? 1 : 0;
1738      } else sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
1739      break;
1740
1741   case SDC_CMD_GETXVAUTOPAINTCOLORKEY:
1742      if(pPriv) {
1743         sdcbuf->sdc_result[0] = pPriv->autopaintColorKey ? 1 : 0;
1744      } else sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
1745      break;
1746
1747   case SDC_CMD_SETXVDEFAULTS:
1748      if(pPriv) {
1749         SISSetPortDefaults(pScrn, pPriv);
1750      } else sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
1751      break;
1752
1753   case SDC_CMD_SETXVDISABLEGFX:
1754      if(pPriv) {
1755         pPriv->disablegfx = sdcbuf->sdc_parm[0] ? 1 : 0;
1756      } else sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
1757      break;
1758
1759   case SDC_CMD_GETXVDISABLEGFX:
1760      if(pPriv) {
1761         sdcbuf->sdc_result[0] = pPriv->disablegfx ? 1 : 0;
1762      } else sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
1763      break;
1764
1765   case SDC_CMD_SETXVDISABLEGFXLR:
1766      if(pPriv) {
1767         pPriv->disablegfxlr = sdcbuf->sdc_parm[0] ? 1 : 0;
1768      } else sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
1769      break;
1770
1771   case SDC_CMD_GETXVDISABLEGFXLR:
1772      if(pPriv) {
1773         sdcbuf->sdc_result[0] = pPriv->disablegfxlr ? 1 : 0;
1774      } else sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
1775      break;
1776
1777   case SDC_CMD_SETXVSWITCHCRT:
1778      if((pPriv) && (pSiS->VGAEngine == SIS_315_VGA)) {
1779         if(pPriv->AllowSwitchCRT) {
1780	    pPriv->crtnum = sdcbuf->sdc_parm[0] ? 1 : 0;
1781#ifdef SISDUALHEAD
1782            if(pPriv->dualHeadMode) pSiSEnt->curxvcrtnum = pPriv->crtnum;
1783#endif
1784	 }
1785      } else sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
1786      break;
1787
1788   case SDC_CMD_GETXVSWITCHCRT:
1789      if((pPriv) && (pSiS->VGAEngine == SIS_315_VGA)) {
1790#ifdef SISDUALHEAD
1791         if(pPriv->dualHeadMode)
1792            sdcbuf->sdc_result[0] = pSiSEnt->curxvcrtnum;
1793         else
1794#endif
1795            sdcbuf->sdc_result[0] = pPriv->crtnum;
1796      } else sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
1797      break;
1798
1799
1800   case SDC_CMD_SETTVXPOS:
1801      {
1802	 int value = sdcbuf->sdc_parm[0] - 32768;
1803	 if((value < -32) || (value > 32)) {
1804	    sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
1805	 } else if(pSiS->xv_sisdirectunlocked) {
1806	    pPriv->tvxpos = value;
1807	    SiS_SetTVxposoffset(pScrn, pPriv->tvxpos);
1808	    pPriv->updatetvxpos = FALSE;
1809         } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
1810      }
1811      break;
1812
1813   case SDC_CMD_GETTVXPOS:
1814      sdcbuf->sdc_result[0] = SiS_GetTVxposoffset(pScrn) + 32768;
1815      break;
1816
1817   case SDC_CMD_SETTVYPOS:
1818      {
1819	 int value = sdcbuf->sdc_parm[0] - 32768;
1820	 if((value < -32) || (value > 32)) {
1821	    sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
1822	 } else if(pSiS->xv_sisdirectunlocked) {
1823	    pPriv->tvypos = value;
1824	    SiS_SetTVyposoffset(pScrn, pPriv->tvypos);
1825	    pPriv->updatetvypos = FALSE;
1826	 } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
1827      }
1828      break;
1829
1830   case SDC_CMD_GETTVYPOS:
1831      sdcbuf->sdc_result[0] = SiS_GetTVyposoffset(pScrn) + 32768;
1832      break;
1833
1834   case SDC_CMD_SETXVDEINT:
1835   case SDC_CMD_GETXVDEINT:
1836      sdcbuf->sdc_result_header = SDC_RESULT_INVAL;
1837      break;
1838
1839   case SDC_CMD_GETMONGAMMACRT1:
1840      sdcbuf->sdc_result[0] = pSiS->CRT1MonGamma;
1841      break;
1842
1843   case SDC_CMD_GETMONGAMMACRT2:
1844      sdcbuf->sdc_result[0] = pSiS->CRT2MonGamma;
1845      break;
1846
1847   case SDC_CMD_LOGQUIET:
1848      pSiS->SCLogQuiet = sdcbuf->sdc_parm[0] ? TRUE : FALSE;
1849      break;
1850
1851   case SDC_CMD_GETCRT1SATGAIN:
1852      sdcbuf->sdc_result[0] = SiS_GetSISCRT1SaturationGain(pScrn);
1853      break;
1854
1855   case SDC_CMD_SETCRT1SATGAIN:
1856      if(pSiS->xv_sisdirectunlocked) {
1857	 SiS_SetSISCRT1SaturationGain(pScrn, (int)sdcbuf->sdc_parm[0]);
1858      } else sdcbuf->sdc_result_header = SDC_RESULT_NOPERM;
1859      break;
1860
1861   default:
1862      sdcbuf->sdc_result_header = SDC_RESULT_UNDEFCMD;
1863   }
1864
1865   return Success;
1866}
1867
1868/* Proc */
1869
1870static int
1871SiSProcSiSCtrlQueryVersion(ClientPtr client)
1872{
1873    xSiSCtrlQueryVersionReply	  rep;
1874    register int		  n;
1875
1876    REQUEST_SIZE_MATCH(xSiSCtrlQueryVersionReq);
1877    rep.type = X_Reply;
1878    rep.length = 0;
1879    rep.sequenceNumber = client->sequence;
1880    rep.majorVersion = SISCTRL_MAJOR_VERSION;
1881    rep.minorVersion = SISCTRL_MINOR_VERSION;
1882    if(client->swapped) {
1883        _swaps(&rep.sequenceNumber, n);
1884        _swapl(&rep.length, n);
1885        _swaps(&rep.majorVersion, n);
1886        _swaps(&rep.minorVersion, n);
1887    }
1888    WriteToClient(client, sizeof(xSiSCtrlQueryVersionReply), (char *)&rep);
1889    return (client->noClientException);
1890}
1891
1892static int
1893SiSProcSiSCtrlCommand(ClientPtr client)
1894{
1895    REQUEST(xSiSCtrlCommandReq);
1896    xSiSCtrlCommandReply rep;
1897    ExtensionEntry 	 *myext;
1898    xSiSCtrlScreenTable  *myctrl;
1899    register int	 n;
1900    int 		 i, ret;
1901
1902    REQUEST_SIZE_MATCH(xSiSCtrlCommandReq);
1903
1904    memcpy(&rep, stuff, sizeof(xSiSCtrlCommandReply));
1905
1906    /* Get pointer to ExtensionEntry */
1907    if(!(myext = CheckExtension(SISCTRL_PROTOCOL_NAME))) return BadMatch;
1908
1909    /* Get pointer to our private */
1910    if(!(myctrl = (xSiSCtrlScreenTable *)myext->extPrivate)) return BadMatch;
1911
1912    /* Check if screen index is within out limits */
1913    if(rep.screen > myctrl->maxscreens) return BadMatch;
1914
1915    /* Check if this screen has added itself */
1916    if(!(myctrl->HandleSiSDirectCommand[rep.screen])) return BadMatch;
1917
1918    /* Finally, execute the command */
1919    if((ret = (myctrl->HandleSiSDirectCommand[rep.screen])(&rep)) != Success)
1920       return ret;
1921
1922    rep.type = X_Reply;
1923    rep.length = (sizeof(xSiSCtrlCommandReply) - sizeof(xGenericReply)) >> 2;
1924    rep.sequenceNumber = client->sequence;
1925
1926    if(client->swapped) {
1927       _swaps(&rep.sequenceNumber, n);
1928       _swapl(&rep.length, n);
1929       _swapl(&rep.screen, n);
1930       _swapl(&rep.sdc_id, n);
1931       _swapl(&rep.sdc_command, n);
1932       _swapl(&rep.sdc_result_header, n);
1933       for(i = 0; i < SDC_NUM_PARM_RESULT; i++) {
1934	  _swapl(&rep.sdc_parm[i], n);
1935	  _swapl(&rep.sdc_result[i], n);
1936       }
1937    }
1938    WriteToClient(client, sizeof(xSiSCtrlCommandReply), (char *)&rep);
1939    return client->noClientException;
1940}
1941
1942static int
1943SiSProcSiSCtrlDispatch(ClientPtr client)
1944{
1945    REQUEST(xReq);
1946    switch(stuff->data) {
1947	case X_SiSCtrlQueryVersion:
1948	     return SiSProcSiSCtrlQueryVersion(client);
1949	case X_SiSCtrlCommand:
1950	     return SiSProcSiSCtrlCommand(client);
1951    }
1952    return BadRequest;
1953}
1954
1955/* SProc */
1956
1957static int
1958SiSSProcSiSCtrlQueryVersion(ClientPtr client)
1959{
1960    REQUEST(xSiSCtrlQueryVersionReq);
1961    register int n;
1962    _swaps(&stuff->length, n);
1963    REQUEST_SIZE_MATCH(xSiSCtrlQueryVersionReq);
1964    return SiSProcSiSCtrlQueryVersion(client);
1965}
1966
1967static int
1968SiSSProcSiSCtrlCommand(ClientPtr client)
1969{
1970    REQUEST(xSiSCtrlCommandReq);
1971    register int n;
1972    int i;
1973    _swaps(&stuff->length, n);
1974    _swapl(&stuff->screen, n);
1975    _swapl(&stuff->sdc_id, n);
1976    _swapl(&stuff->sdc_command, n);
1977    _swapl(&stuff->sdc_result_header, n);
1978    for(i = 0; i < SDC_NUM_PARM_RESULT; i++) {
1979       _swapl(&stuff->sdc_parm[i], n);
1980       _swapl(&stuff->sdc_result[i], n);
1981    }
1982    REQUEST_SIZE_MATCH(xSiSCtrlCommandReq);
1983    return SiSProcSiSCtrlCommand(client);
1984}
1985
1986static int
1987SiSSProcSiSCtrlDispatch(ClientPtr client)
1988{
1989    REQUEST(xReq);
1990    switch(stuff->data) {
1991       case X_SiSCtrlQueryVersion:
1992	  return SiSSProcSiSCtrlQueryVersion(client);
1993       case X_SiSCtrlCommand:
1994	  return SiSSProcSiSCtrlCommand(client);
1995    }
1996    return BadRequest;
1997}
1998
1999static void
2000SiSCtrlResetProc(ExtensionEntry* extEntry)
2001{
2002    /* Called by CloseDownExtensions() */
2003    /* (CloseDownExtensions() is called BEFORE CloseScreen,
2004     * which is why we must not use pSiS->SiSCtrlExtEntry
2005     * in SiSCtrlExtUnregister())
2006     */
2007    if(extEntry->extPrivate) {
2008       free(extEntry->extPrivate);
2009       extEntry->extPrivate = NULL;
2010    }
2011}
2012
2013void
2014SiSCtrlExtInit(ScrnInfoPtr pScrn)
2015{
2016   SISPtr pSiS = SISPTR(pScrn);
2017   ExtensionEntry  *myext;
2018   xSiSCtrlScreenTable *myctrl;
2019   unsigned int version, revision;
2020
2021   if((pSiS->VGAEngine != SIS_300_VGA) &&
2022      (pSiS->VGAEngine != SIS_315_VGA))
2023      return;
2024
2025   pSiS->SCLogQuiet = FALSE;
2026
2027   if(!(myext = CheckExtension(SISCTRL_PROTOCOL_NAME))) {
2028
2029      if(!(myctrl = calloc(sizeof(xSiSCtrlScreenTable), 1)))
2030         return;
2031
2032      if(!(myext = AddExtension(SISCTRL_PROTOCOL_NAME, 0, 0,
2033				SiSProcSiSCtrlDispatch,
2034				SiSSProcSiSCtrlDispatch,
2035				SiSCtrlResetProc,
2036				StandardMinorOpcode))) {
2037         xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
2038	 		"Failed to add SISCTRL extension\n");
2039	 free(myctrl);
2040	 return;
2041      }
2042
2043      myext->extPrivate = (pointer)myctrl;
2044
2045      myctrl->maxscreens = SISCTRL_MAX_SCREENS;
2046      myctrl->version_major = version = SISCTRL_MAJOR_VERSION;
2047      myctrl->version_minor = revision = SISCTRL_MINOR_VERSION;
2048
2049      xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2050		"Initialized SISCTRL extension version %d.%d\n",
2051		version, revision);
2052
2053   } else {
2054
2055      if(!(myctrl = (xSiSCtrlScreenTable *)myext->extPrivate)) {
2056         xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
2057		"Internal error: Found SISCTRL extension with NULL-private!\n");
2058	 return;
2059      }
2060
2061      version = myctrl->version_major;
2062      revision = myctrl->version_minor;
2063   }
2064
2065   if(pScrn->scrnIndex < myctrl->maxscreens) {
2066
2067      myctrl->HandleSiSDirectCommand[pScrn->scrnIndex] = SiSHandleSiSDirectCommand;
2068
2069      pSiS->SiSCtrlExtEntry = myext;
2070
2071      xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2072		"Registered screen %d with SISCTRL extension version %d.%d\n",
2073		pScrn->scrnIndex, version, revision);
2074   } else {
2075
2076      xf86DrvMsg(pScrn->scrnIndex, X_INFO,
2077		"Screen number (%d) too high for SISCTRL extension %d.%d\n",
2078		pScrn->scrnIndex, version, revision);
2079
2080   }
2081
2082}
2083
2084void
2085SiSCtrlExtUnregister(SISPtr pSiS, int index)
2086{
2087   ExtensionEntry  *myext;
2088   xSiSCtrlScreenTable *myctrl;
2089
2090   if(!pSiS->SiSCtrlExtEntry) return;
2091
2092   /* Since CloseDownExtensions() is called before
2093    * our CloseScreen(), we must not use the saved
2094    * ptr here, but instead check for the extension.
2095    */
2096
2097   if((myext = CheckExtension(SISCTRL_PROTOCOL_NAME))) {
2098      if((myctrl = (xSiSCtrlScreenTable *)myext->extPrivate)) {
2099         myctrl->HandleSiSDirectCommand[index] = NULL;
2100      }
2101   }
2102}
2103
2104/***********************************
2105 *     Xv attribute interface      *
2106 ***********************************/
2107
2108#ifdef XV_SD_DEPRECATED
2109
2110int
2111SISSetPortUtilAttribute(ScrnInfoPtr pScrn, Atom attribute,
2112			INT32 value, SISPortPrivPtr pPriv)
2113{
2114  SISPtr pSiS = SISPTR(pScrn);
2115#ifdef SISDUALHEAD
2116  SISEntPtr pSiSEnt = pSiS->entityPrivate;;
2117#endif
2118
2119  if(attribute == pSiS->xv_USD) {
2120     if(pSiS->enablesisctrl) {
2121	 if(value == SIS_DIRECTKEY) {
2122	   pSiS->xv_sisdirectunlocked++;
2123	} else if(pSiS->xv_sisdirectunlocked) {
2124	   pSiS->xv_sisdirectunlocked--;
2125	}
2126     } else {
2127	pSiS->xv_sisdirectunlocked = 0;
2128     }
2129  } else if(attribute == pSiS->xv_SVF) {
2130#ifdef SISDUALHEAD
2131     if(!pPriv->dualHeadMode)
2132#endif
2133	if(pSiS->xv_sisdirectunlocked) {
2134	   SISSwitchCRT2Type(pScrn, (ULong)value, FALSE);
2135	   SISUpdateVideoParms(pSiS, pPriv);
2136	}
2137  } else if(attribute == pSiS->xv_CT1) {
2138#ifdef SISDUALHEAD
2139     if(!pPriv->dualHeadMode)
2140#endif
2141	if(pSiS->xv_sisdirectunlocked) {
2142	   SISSwitchCRT1Status(pScrn, (ULong)value, FALSE);
2143	   SISUpdateVideoParms(pSiS, pPriv);
2144        }
2145  } else if(attribute == pSiS->xv_RDT) {
2146#ifdef SISDUALHEAD
2147     if(!pPriv->dualHeadMode)
2148#endif
2149	if(pSiS->xv_sisdirectunlocked) {
2150	   SISRedetectCRT2Devices(pScrn);
2151	}
2152  } else if(attribute == pSiS->xv_TAF) {
2153     if(pSiS->xv_sisdirectunlocked) {
2154	SiS_SetSISTVantiflicker(pScrn, (int)value);
2155     }
2156  } else if(attribute == pSiS->xv_TSA) {
2157     if(pSiS->xv_sisdirectunlocked) {
2158	SiS_SetSISTVsaturation(pScrn, (int)value);
2159     }
2160  } else if(attribute == pSiS->xv_TEE) {
2161     if(pSiS->xv_sisdirectunlocked) {
2162	SiS_SetSISTVedgeenhance(pScrn, (int)value);
2163     }
2164  } else if(attribute == pSiS->xv_CFI) {
2165     if(pSiS->xv_sisdirectunlocked) {
2166	SiS_SetSISTVcfilter(pScrn, value ? 1 : 0);
2167     }
2168  } else if(attribute == pSiS->xv_YFI) {
2169     if(pSiS->xv_sisdirectunlocked) {
2170	SiS_SetSISTVyfilter(pScrn, value);
2171     }
2172  } else if(attribute == pSiS->xv_COC) {
2173     if(pSiS->xv_sisdirectunlocked) {
2174	SiS_SetSISTVcolcalib(pScrn, (int)value, TRUE);
2175     }
2176  } else if(attribute == pSiS->xv_COF) {
2177     if(pSiS->xv_sisdirectunlocked) {
2178	SiS_SetSISTVcolcalib(pScrn, (int)value, FALSE);
2179     }
2180  } else if(attribute == pSiS->xv_TCO) {
2181     if(pSiS->xv_sisdirectunlocked) {
2182	SiS_SetCHTVcontrast(pScrn, (int)value);
2183     }
2184  } else if(attribute == pSiS->xv_TTE) {
2185     if(pSiS->xv_sisdirectunlocked) {
2186	SiS_SetCHTVtextenhance(pScrn, (int)value);
2187     }
2188  } else if(attribute == pSiS->xv_TCF) {
2189     if(pSiS->xv_sisdirectunlocked) {
2190	SiS_SetCHTVchromaflickerfilter(pScrn, (int)value);
2191     }
2192  } else if(attribute == pSiS->xv_TLF) {
2193     if(pSiS->xv_sisdirectunlocked) {
2194	SiS_SetCHTVlumaflickerfilter(pScrn, (int)value);
2195     }
2196  } else if(attribute == pSiS->xv_TCC) {
2197     if(pSiS->xv_sisdirectunlocked) {
2198	SiS_SetCHTVcvbscolor(pScrn, value ? 1 : 0);
2199     }
2200  } else if(attribute == pSiS->xv_OVR) {
2201     if(pSiS->xv_sisdirectunlocked) {
2202	pSiS->UseCHOverScan = -1;
2203	pSiS->OptTVSOver = FALSE;
2204	if(value == 3) {
2205	   if(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTSOVER) {
2206	      pSiS->OptTVSOver = TRUE;
2207	   }
2208	   pSiS->UseCHOverScan = 1;
2209	} else if(value == 2) pSiS->UseCHOverScan = 1;
2210	else if(value == 1)   pSiS->UseCHOverScan = 0;
2211     }
2212  } else if(attribute == pSiS->xv_CMD) {
2213     if(pSiS->xv_sisdirectunlocked) {
2214	int result = 0;
2215	pSiS->xv_sd_result = (value & 0xffffff00);
2216	result = SISCheckModeIndexForCRT2Type(pScrn, (UShort)(value & 0xff),
2217					      (UShort)((value >> 8) & 0xff),
2218					      FALSE);
2219	pSiS->xv_sd_result |= (result & 0xff);
2220     }
2221  } else if(attribute == pSiS->xv_SGA) {
2222     if(pSiS->xv_sisdirectunlocked) {
2223	Bool backup = pSiS->XvGamma;
2224	Bool backup2 = pSiS->CRT2SepGamma;
2225	pSiS->CRT1gamma = (value & 0x01) ? TRUE : FALSE;
2226	pSiS->CRT2gamma = (value & 0x02) ? TRUE : FALSE;
2227#ifdef SISDUALHEAD
2228	if(pPriv->dualHeadMode) {
2229	   pSiSEnt->CRT1gamma = pSiS->CRT1gamma;
2230	   pSiSEnt->CRT2gamma = pSiS->CRT2gamma;
2231	}
2232#endif
2233	if(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTSGRCRT2) {
2234	   pSiS->CRT2SepGamma = (value & 0x08) ? TRUE : FALSE;
2235	   if(pSiS->CRT2SepGamma != backup2) {
2236	      if(pSiS->CRT2SepGamma) {
2237		 SiS_UpdateGammaCRT2(pScrn);
2238	      }
2239#ifdef SISGAMMARAMP
2240	      else {
2241		 SISCalculateGammaRamp(pScrn->pScreen, pScrn);
2242	      }
2243#endif
2244	      /* ATTN: When disabling CRT2 sep gamma,
2245	       * as long as SISGAMMARAMP is not defined,
2246	       * application needs to reset palette using
2247	       * vidmodextension! (See SiS_SD_CANSETGAMMA)
2248	       *
2249	       * Note: Difference between setting gamma values
2250	       * for CRT1 and CRT2: For CRT1, driver only
2251	       * stores the values, but does nothing with them.
2252	       * For CRT2, the driver will IMMEDIATELY recalc
2253	       * the palette. App needs to calc gamma ramp
2254	       * itself for CRT1, and set it using the
2255	       * VidModExtention.
2256	       */
2257	   }
2258	} else pSiS->CRT2SepGamma = FALSE;
2259	pSiS->XvGamma = (value & 0x04) ? TRUE : FALSE;
2260	if(pSiS->VGAEngine == SIS_315_VGA) {
2261	   if(backup != pSiS->XvGamma) {
2262	      SiSUpdateXvGamma(pSiS, pPriv);
2263	   }
2264	}
2265     }
2266  } else if(attribute == pSiS->xv_TXS) {
2267     if((value < -16) || (value > 16)) return BadValue;
2268     if(pSiS->xv_sisdirectunlocked) {
2269	SiS_SetTVxscale(pScrn, value);
2270     }
2271  } else if(attribute == pSiS->xv_TYS) {
2272     if((value < -4) || (value > 3)) return BadValue;
2273     if(pSiS->xv_sisdirectunlocked) {
2274	SiS_SetTVyscale(pScrn, value);
2275     }
2276  } else if(attribute == pSiS->xv_BRR) {
2277     if((value < 100) || (value > 10000)) return BadValue;
2278     if(pSiS->xv_sisdirectunlocked) {
2279	pSiS->GammaBriR = value;
2280     }
2281  } else if(attribute == pSiS->xv_BRG) {
2282     if((value < 100) || (value > 10000)) return BadValue;
2283     if(pSiS->xv_sisdirectunlocked) {
2284	pSiS->GammaBriG = value;
2285     }
2286  } else if(attribute == pSiS->xv_BRB) {
2287     if((value < 100) || (value > 10000)) return BadValue;
2288     if(pSiS->xv_sisdirectunlocked) {
2289	pSiS->GammaBriB = value;
2290     }
2291  } else if(attribute == pSiS->xv_PBR) {
2292     /* Nop */
2293  } else if(attribute == pSiS->xv_PBG) {
2294     /* Nop */
2295  } else if(attribute == pSiS->xv_PBB) {
2296     /* Nop */
2297  } else if(attribute == pSiS->xv_BRR2) {
2298     if((value < 100) || (value > 10000)) return BadValue;
2299     if(pSiS->xv_sisdirectunlocked) {
2300#ifdef SISDUALHEAD
2301	if(pPriv->dualHeadMode) pSiSEnt->GammaBriR = value;
2302#endif
2303     }
2304  } else if(attribute == pSiS->xv_BRG2) {
2305     if((value < 100) || (value > 10000)) return BadValue;
2306     if(pSiS->xv_sisdirectunlocked) {
2307#ifdef SISDUALHEAD
2308	if(pPriv->dualHeadMode) pSiSEnt->GammaBriG = value;
2309#endif
2310     }
2311  } else if(attribute == pSiS->xv_BRB2) {
2312     if((value < 100) || (value > 10000)) return BadValue;
2313     if(pSiS->xv_sisdirectunlocked) {
2314#ifdef SISDUALHEAD
2315	if(pPriv->dualHeadMode) pSiSEnt->GammaBriB = value;
2316#endif
2317     }
2318  } else if(attribute == pSiS->xv_PBR2) {
2319     /* Nop */
2320  } else if(attribute == pSiS->xv_PBG2) {
2321     /* Nop */
2322  } else if(attribute == pSiS->xv_PBB2) {
2323     /* Nop */
2324  } else if(attribute == pSiS->xv_GARC2) {
2325     if((value < 100) || (value > 10000)) return BadValue;
2326     if(pSiS->xv_sisdirectunlocked) {
2327	pSiS->GammaR2 = (float)value / (float)1000;
2328	SiS_UpdateGammaCRT2(pScrn);
2329     }
2330  } else if(attribute == pSiS->xv_GAGC2) {
2331     if((value < 100) || (value > 10000)) return BadValue;
2332     if(pSiS->xv_sisdirectunlocked) {
2333	pSiS->GammaG2 = (float)value / (float)1000;
2334	SiS_UpdateGammaCRT2(pScrn);
2335     }
2336  } else if(attribute == pSiS->xv_GABC2) {
2337     if((value < 100) || (value > 10000)) return BadValue;
2338     if(pSiS->xv_sisdirectunlocked) {
2339	pSiS->GammaB2 = (float)value / (float)1000;
2340	SiS_UpdateGammaCRT2(pScrn);
2341     }
2342  } else if(attribute == pSiS->xv_BRRC2) {
2343     if((value < 100) || (value > 10000)) return BadValue;
2344     if(pSiS->xv_sisdirectunlocked) {
2345	pSiS->GammaBriR2 = value;
2346	SiS_UpdateGammaCRT2(pScrn);
2347     }
2348  } else if(attribute == pSiS->xv_BRGC2) {
2349     if((value < 100) || (value > 10000)) return BadValue;
2350     if(pSiS->xv_sisdirectunlocked) {
2351	pSiS->GammaBriG2 = value;
2352	SiS_UpdateGammaCRT2(pScrn);
2353     }
2354  } else if(attribute == pSiS->xv_BRBC2) {
2355     if((value < 100) || (value > 10000)) return BadValue;
2356     if(pSiS->xv_sisdirectunlocked) {
2357	pSiS->GammaBriB2 = value;
2358	SiS_UpdateGammaCRT2(pScrn);
2359     }
2360  } else if(attribute == pSiS->xv_PBRC2) {
2361     /* Nop */
2362  } else if(attribute == pSiS->xv_PBGC2) {
2363     /* Nop */
2364  } else if(attribute == pSiS->xv_PBBC2) {
2365     /* Nop */
2366  } else if(attribute == pSiS->xv_SHC) {
2367     if(pSiS->xv_sisdirectunlocked) {
2368	Bool VisibleBackup = pSiS->HWCursorIsVisible;
2369	pSiS->HideHWCursor = value ? TRUE : FALSE;
2370	if(pSiS->CursorInfoPtr) {
2371	   if(VisibleBackup) {
2372	      if(value) {
2373		 (pSiS->CursorInfoPtr->HideCursor)(pScrn);
2374	      } else {
2375		 (pSiS->CursorInfoPtr->ShowCursor)(pScrn);
2376	      }
2377	   }
2378	   pSiS->HWCursorIsVisible = VisibleBackup;
2379	}
2380     }
2381  } else if(attribute == pSiS->xv_PMD) {
2382     if(pSiS->xv_sisdirectunlocked) {
2383        if(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTSCALE) {
2384	   if(value & 0x01)      pSiS->SiS_Pr->UsePanelScaler = -1;
2385	   else if(value & 0x02) pSiS->SiS_Pr->UsePanelScaler = 1;
2386	   else			 pSiS->SiS_Pr->UsePanelScaler = 0;
2387	   if(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTCENTER) {
2388	      if(value & 0x04)      pSiS->SiS_Pr->CenterScreen = -1;
2389	      else if(value & 0x08) pSiS->SiS_Pr->CenterScreen = 1;
2390	      else		    pSiS->SiS_Pr->CenterScreen = 0;
2391	   }
2392        }
2393     }
2394#ifdef TWDEBUG
2395  } else if(attribute == pSiS->xv_STR) {
2396     ULong port;
2397     CARD8 reg;
2398     switch((value & 0xff000000) >> 24) {
2399     case 0x00: port = SISSR;    break;
2400     case 0x01: port = SISPART1; break;
2401     case 0x02: port = SISPART2; break;
2402     case 0x03: port = SISPART3; break;
2403     case 0x04: port = SISPART4; break;
2404     case 0x05: port = SISCR;    break;
2405     case 0x06: port = SISVID;   break;
2406     default:   return BadValue;
2407     }
2408     outSISIDXREG(port,((value & 0x00ff0000) >> 16), ((value & 0x0000ff00) >> 8));
2409     inSISIDXREG(port, ((value & 0x00ff0000) >> 16), reg);
2410     xf86DrvMsg(0, 0, "SetREG %x -> %x -> %x\n", ((value & 0x00ff0000) >> 16), ((value & 0x0000ff00) >> 8), reg);
2411#endif
2412  } else {
2413     return BadMatch;
2414  }
2415
2416  return Success;
2417}
2418
2419int
2420SISGetPortUtilAttribute(ScrnInfoPtr pScrn,  Atom attribute,
2421			INT32 *value, SISPortPrivPtr pPriv)
2422{
2423  SISPtr pSiS = SISPTR(pScrn);
2424#ifdef SISDUALHEAD
2425  SISEntPtr pSiSEnt = pSiS->entityPrivate;;
2426#endif
2427
2428  if(attribute == pSiS->xv_QVF) {
2429     *value = pSiS->VBFlags;
2430  } else if(attribute == pSiS->xv_GDV) {
2431     *value = SISDRIVERIVERSION;
2432  } else if(attribute == pSiS->xv_GHI) {
2433     *value = (pSiS->ChipFlags & 0xffff) | (pSiS->ChipType << 16) | (pSiS->ChipRev << 24);
2434  } else if(attribute == pSiS->xv_GBI) {
2435     *value = (pSiS->PciBus << 16) | (pSiS->PciDevice << 8) | pSiS->PciFunc;
2436  } else if(attribute == pSiS->xv_QVV) {
2437     *value = SIS_VBFlagsVersion;
2438  } else if(attribute == pSiS->xv_QDD) {
2439     *value = pSiS->detectedCRT2Devices;
2440  } else if(attribute == pSiS->xv_CT1) {
2441     *value = pSiS->CRT1isoff ? 0 : 1;
2442  } else if(attribute == pSiS->xv_GSF) {
2443     *value = pSiS->SiS_SD_Flags;
2444  } else if(attribute == pSiS->xv_GSF2) {
2445     *value = pSiS->SiS_SD2_Flags;
2446  } else if(attribute == pSiS->xv_USD) {
2447     *value = pSiS->xv_sisdirectunlocked;
2448  } else if(attribute == pSiS->xv_TAF) {
2449     *value = SiS_GetSISTVantiflicker(pScrn);
2450  } else if(attribute == pSiS->xv_TSA) {
2451     *value = SiS_GetSISTVsaturation(pScrn);
2452  } else if(attribute == pSiS->xv_TEE) {
2453     *value = SiS_GetSISTVedgeenhance(pScrn);
2454  } else if(attribute == pSiS->xv_CFI) {
2455     *value = SiS_GetSISTVcfilter(pScrn);
2456  } else if(attribute == pSiS->xv_YFI) {
2457     *value = SiS_GetSISTVyfilter(pScrn);
2458  } else if(attribute == pSiS->xv_COC) {
2459     *value = SiS_GetSISTVcolcalib(pScrn, TRUE);
2460  } else if(attribute == pSiS->xv_COF) {
2461     *value = SiS_GetSISTVcolcalib(pScrn, FALSE);
2462  } else if(attribute == pSiS->xv_TCO) {
2463     *value = SiS_GetCHTVcontrast(pScrn);
2464  } else if(attribute == pSiS->xv_TTE) {
2465     *value = SiS_GetCHTVtextenhance(pScrn);
2466  } else if(attribute == pSiS->xv_TCF) {
2467     *value = SiS_GetCHTVchromaflickerfilter(pScrn);
2468  } else if(attribute == pSiS->xv_TLF) {
2469     *value = SiS_GetCHTVlumaflickerfilter(pScrn);
2470  } else if(attribute == pSiS->xv_TCC) {
2471     *value = SiS_GetCHTVcvbscolor(pScrn);
2472  } else if(attribute == pSiS->xv_CMDR) {
2473     *value = pSiS->xv_sd_result;
2474  } else if(attribute == pSiS->xv_OVR) {
2475     /* Changing of CRT2 settings not supported in DHM! */
2476     *value = 0;
2477     if(pSiS->OptTVSOver == 1)         *value = 3;
2478     else if(pSiS->UseCHOverScan == 1) *value = 2;
2479     else if(pSiS->UseCHOverScan == 0) *value = 1;
2480  } else if(attribute == pSiS->xv_SGA) {
2481     *value = 0;
2482#ifdef SISDUALHEAD
2483     if(pPriv->dualHeadMode) {
2484        if(pSiSEnt->CRT1gamma) *value |= 0x01;
2485	if(pSiSEnt->CRT2gamma) *value |= 0x02;
2486     } else {
2487#endif
2488	if(pSiS->CRT1gamma)    *value |= 0x01;
2489	if(pSiS->CRT2gamma)    *value |= 0x02;
2490	if(pSiS->CRT2SepGamma) *value |= 0x08;
2491#ifdef SISDUALHEAD
2492     }
2493#endif
2494     if(pSiS->XvGamma) *value |= 0x04;
2495  } else if(attribute == pSiS->xv_TXS) {
2496     *value = SiS_GetTVxscale(pScrn);
2497  } else if(attribute == pSiS->xv_TYS) {
2498     *value = SiS_GetTVyscale(pScrn);
2499  } else if(attribute == pSiS->xv_GSS) {
2500     *value = (pScrn->virtualX << 16) | pScrn->virtualY;
2501  } else if(attribute == pSiS->xv_BRR) {
2502     *value = pSiS->GammaBriR;
2503  } else if(attribute == pSiS->xv_BRG) {
2504     *value = pSiS->GammaBriG;
2505  } else if(attribute == pSiS->xv_BRB) {
2506     *value = pSiS->GammaBriB;
2507  } else if(attribute == pSiS->xv_PBR) {
2508     *value = 1000;
2509  } else if(attribute == pSiS->xv_PBG) {
2510     *value = 1000;
2511  } else if(attribute == pSiS->xv_PBB) {
2512     *value = 1000;
2513  } else if(attribute == pSiS->xv_BRR2) {
2514#ifdef SISDUALHEAD
2515     if(pPriv->dualHeadMode) *value = pSiSEnt->GammaBriR;
2516     else
2517#endif
2518          *value = pSiS->GammaBriR;
2519  } else if(attribute == pSiS->xv_BRG2) {
2520#ifdef SISDUALHEAD
2521     if(pPriv->dualHeadMode) *value = pSiSEnt->GammaBriG;
2522     else
2523#endif
2524          *value = pSiS->GammaBriG;
2525  } else if(attribute == pSiS->xv_BRB2) {
2526#ifdef SISDUALHEAD
2527     if(pPriv->dualHeadMode) *value = pSiSEnt->GammaBriB;
2528     else
2529#endif
2530          *value = pSiS->GammaBriB;
2531  } else if(attribute == pSiS->xv_PBR2) {
2532     *value = 1000;
2533  } else if(attribute == pSiS->xv_PBG2) {
2534     *value = 1000;
2535  } else if(attribute == pSiS->xv_PBB2) {
2536     *value = 1000;
2537  } else if(attribute == pSiS->xv_GARC2) {
2538     *value = (int)(pSiS->GammaR2 * 1000);
2539  } else if(attribute == pSiS->xv_GAGC2) {
2540     *value = (int)(pSiS->GammaG2 * 1000);
2541  } else if(attribute == pSiS->xv_GABC2) {
2542     *value = (int)(pSiS->GammaB2 * 1000);
2543  } else if(attribute == pSiS->xv_BRRC2) {
2544     *value = pSiS->GammaBriR2;
2545  } else if(attribute == pSiS->xv_BRGC2) {
2546     *value = pSiS->GammaBriG2;
2547  } else if(attribute == pSiS->xv_BRBC2) {
2548     *value = pSiS->GammaBriB2;
2549  } else if(attribute == pSiS->xv_PBRC2) {
2550     *value = 1000;
2551  } else if(attribute == pSiS->xv_PBGC2) {
2552     *value = 1000;
2553  } else if(attribute == pSiS->xv_PBBC2) {
2554     *value = 1000;
2555  } else if(attribute == pSiS->xv_SHC) {
2556     *value = pSiS->HideHWCursor ? 1 : 0;
2557  } else if(attribute == pSiS->xv_PMD) {
2558     *value = 0;
2559     if(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTSCALE) {
2560        switch(pSiS->SiS_Pr->UsePanelScaler) {
2561           case -1: *value |= 0x01; break;
2562           case 1:  *value |= 0x02; break;
2563        }
2564	if(pSiS->SiS_SD_Flags & SiS_SD_SUPPORTCENTER) {
2565           switch(pSiS->SiS_Pr->CenterScreen) {
2566              case -1: *value |= 0x04; break;
2567              case 1:  *value |= 0x08; break;
2568           }
2569	}
2570     }
2571  } else {
2572     return BadMatch;
2573  }
2574
2575  return Success;
2576}
2577
2578#endif /* XV_SD_DEPRECATED */
2579
2580