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