1dfe64dd3Smacallan/*
2dfe64dd3Smacallan * Basic hardware and memory detection
3dfe64dd3Smacallan *
4dfe64dd3Smacallan * Copyright (C) 2001-2004 by Thomas Winischhofer, Vienna, Austria.
5dfe64dd3Smacallan *
6dfe64dd3Smacallan * Redistribution and use in source and binary forms, with or without
7dfe64dd3Smacallan * modification, are permitted provided that the following conditions
8dfe64dd3Smacallan * are met:
9dfe64dd3Smacallan * 1) Redistributions of source code must retain the above copyright
10dfe64dd3Smacallan *    notice, this list of conditions and the following disclaimer.
11dfe64dd3Smacallan * 2) Redistributions in binary form must reproduce the above copyright
12dfe64dd3Smacallan *    notice, this list of conditions and the following disclaimer in the
13dfe64dd3Smacallan *    documentation and/or other materials provided with the distribution.
14dfe64dd3Smacallan * 3) The name of the author may not be used to endorse or promote products
15dfe64dd3Smacallan *    derived from this software without specific prior written permission.
16dfe64dd3Smacallan *
17dfe64dd3Smacallan * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESSED OR
18dfe64dd3Smacallan * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19dfe64dd3Smacallan * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20dfe64dd3Smacallan * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21dfe64dd3Smacallan * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22dfe64dd3Smacallan * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23dfe64dd3Smacallan * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24dfe64dd3Smacallan * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25dfe64dd3Smacallan * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26dfe64dd3Smacallan * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27dfe64dd3Smacallan *
28dfe64dd3Smacallan * Author:  	Thomas Winischhofer <thomas@winischhofer.net>
29dfe64dd3Smacallan *
30dfe64dd3Smacallan * Ideas and methods for old series based on code by Can-Ru Yeou, XGI Inc.
31dfe64dd3Smacallan *
32dfe64dd3Smacallan */
33dfe64dd3Smacallan
34dfe64dd3Smacallan#ifdef HAVE_CONFIG_H
35dfe64dd3Smacallan#include "config.h"
36dfe64dd3Smacallan#endif
37dfe64dd3Smacallan
38dfe64dd3Smacallan#include "xf86PciInfo.h"
39dfe64dd3Smacallan#include "xf86Pci.h"
40dfe64dd3Smacallan#include "xf86.h"
41dfe64dd3Smacallan#include "fb.h"
42dfe64dd3Smacallan#include "xf86_OSproc.h"
43dfe64dd3Smacallan#include "xorgVersion.h"
44dfe64dd3Smacallan
45dfe64dd3Smacallan#include "xf86cmap.h"
46dfe64dd3Smacallan
47dfe64dd3Smacallan#include "xgi.h"
48dfe64dd3Smacallan#include "xgi_regs.h"
49dfe64dd3Smacallan#include "xgi_dac.h"
50098ad5bdSmacallan#include "xgi_driver.h"
51dfe64dd3Smacallan/* #include "valid_mode.h" */
52dfe64dd3Smacallan
53dfe64dd3Smacallan#define _XF86DGA_SERVER_
54098ad5bdSmacallan#include <X11/extensions/xf86dgaproto.h>
55dfe64dd3Smacallan
56dfe64dd3Smacallan#include "globals.h"
57dfe64dd3Smacallan#ifdef HAVE_XEXTPROTO_71
58dfe64dd3Smacallan#include <X11/extensions/dpmsconst.h>
59dfe64dd3Smacallan#else
60dfe64dd3Smacallan#define DPMS_SERVER
61dfe64dd3Smacallan#include <X11/extensions/dpms.h>
62dfe64dd3Smacallan#endif
63dfe64dd3Smacallan
64dfe64dd3Smacallan
65dfe64dd3Smacallan#include "vb_def.h"
66dfe64dd3Smacallanextern  int  FbDevExist;
67dfe64dd3Smacallan
68dfe64dd3Smacallanstatic Bool bAccessVGAPCIInfo(PXGI_HW_DEVICE_INFO pHwDevInfo, ULONG ulOffset,
69098ad5bdSmacallan    ULONG ulSet, CARD32 *pulValue);
70dfe64dd3Smacallanstatic Bool bAccessNBridgePCIInfo(PXGI_HW_DEVICE_INFO pHwDevInfo,
71dfe64dd3Smacallan    ULONG ulOffset, ULONG ulSet, ULONG *pulValue);
72dfe64dd3Smacallanstatic Bool XGI_IsXG21(ScrnInfoPtr pScrn);
73dfe64dd3Smacallan
74dfe64dd3Smacallanstatic void XGI_InitHwDevInfo(ScrnInfoPtr pScrn);
75dfe64dd3Smacallan
76dfe64dd3Smacallan/* Jong 10/16/2007; merge code */
77dfe64dd3Smacallanstatic void
78dfe64dd3SmacallanxgiXG2X_Setup(ScrnInfoPtr pScrn)
79dfe64dd3Smacallan{
80dfe64dd3Smacallan
81dfe64dd3Smacallan/*********************************************************************
82dfe64dd3Smacallan * Setup
83dfe64dd3Smacallan * Decide the following item of execution data:
84dfe64dd3Smacallan *
85dfe64dd3Smacallan * pXGI->BusWidth
86dfe64dd3Smacallan * pXGI->videoRam (with KB unit)
87dfe64dd3Smacallan * pXGI->CursorOffset (with Byte Unit)
88dfe64dd3Smacallan * pXGI->cmdQueueSize (with Byte Unit)
89dfe64dd3Smacallan * pXGI->cmdQueueSizeMask (with Byte Unit)
90dfe64dd3Smacallan * pXGI->cmdQueueOffset (with Byte Unit)
91dfe64dd3Smacallan * pXGI->cmdQueueLen = 0 ; // init value
92dfe64dd3Smacallan * pXGI->cmdQueueLenMin = 0x200 ; // init value
93dfe64dd3Smacallan * pXGI->cmdQueueLenMax = pXGI->cmdQueueSize -  pXGI->cmdQueueLenMin ;
94dfe64dd3Smacallan *********************************************************************/
95dfe64dd3Smacallan
96dfe64dd3Smacallan    XGIPtr        pXGI = XGIPTR(pScrn);
97dfe64dd3Smacallan    unsigned int  ulMemConfig = 0;
98dfe64dd3Smacallan    unsigned long ulMemSize   = 0;
99dfe64dd3Smacallan    unsigned long ulDramType  = 0;
100dfe64dd3Smacallan    char *dramTypeStr ;
101dfe64dd3Smacallan    unsigned long ulTemp ;
102dfe64dd3Smacallan
103dfe64dd3Smacallan    /* DumpDDIName("xgiXG2X_Setup()\n") ; */
104dfe64dd3Smacallan
105dfe64dd3Smacallan    inXGIIDXREG(XGICR, 0x48, ulTemp) ;
106dfe64dd3Smacallan    if(ulTemp & (1<<0)) /* GPIOH, CR48 D[0] read */
107dfe64dd3Smacallan    {
108dfe64dd3Smacallan        dramTypeStr = "DDRII DRAM" ;
109dfe64dd3Smacallan    }
110dfe64dd3Smacallan    else
111dfe64dd3Smacallan    {
112dfe64dd3Smacallan        dramTypeStr = "DDR DRAM" ;
113dfe64dd3Smacallan    }
114dfe64dd3Smacallan
115dfe64dd3Smacallan
116dfe64dd3Smacallan    pXGI->MemClock = XG40Mclk(pXGI);
117dfe64dd3Smacallan
118dfe64dd3Smacallan    /*********************************************************************************************************
119dfe64dd3Smacallan     * SR14 DRAM Size Register
120dfe64dd3Smacallan     *     Default value: XXh
121dfe64dd3Smacallan     *     D[7:4]    Memory size per channel {BChMemSize}
122dfe64dd3Smacallan     *         0011: 8 MB
123dfe64dd3Smacallan     *         0100: 16 MB
124dfe64dd3Smacallan     *         0101: 32 MB
125dfe64dd3Smacallan     *         0110: 64 MB
126dfe64dd3Smacallan     *         0111: 128 MB
127dfe64dd3Smacallan     *         1000: 256MB
128dfe64dd3Smacallan     *        others: reserved
129dfe64dd3Smacallan     *     D[3:2]    Number of  dram channels [1:0] {BChNum}
130dfe64dd3Smacallan     *         00: uni-channel
131dfe64dd3Smacallan     *         01: reserved
132dfe64dd3Smacallan     *         10: dual-channel.
133dfe64dd3Smacallan     *         11: quad-channel
134dfe64dd3Smacallan     *     D1  Data width per channel selection {BDataWidth}
135dfe64dd3Smacallan     *         0: 32-bits
136dfe64dd3Smacallan     *         1: 64-bits
137dfe64dd3Smacallan     *     D0  Dram channel mapping {BReverseChMapping}
138dfe64dd3Smacallan     *         0: Normal mapping
139dfe64dd3Smacallan     *         1: Reversal mapping
140dfe64dd3Smacallan     *             Dual-channel: Logical channel A/B to physical channel B/A
141dfe64dd3Smacallan     *             Quad-channel: Logical  channel A/B/C/D to physical channel C/D/A/B
142dfe64dd3Smacallan     *
143dfe64dd3Smacallan     *********************************************************************************************************/
144dfe64dd3Smacallan
145dfe64dd3Smacallan    outXGIIDXREG(XGISR, 0x5, 0x86) ;
146dfe64dd3Smacallan    inXGIIDXREG(XGISR, 0x14, ulMemConfig) ;
147dfe64dd3Smacallan    inXGIIDXREG(XGISR, 0x3A, ulDramType) ;
148dfe64dd3Smacallan
149dfe64dd3Smacallan    PDEBUG(ErrorF("xg40_Setup(): ulMemConfig = %02X\n",ulMemConfig)) ;
150dfe64dd3Smacallan    PDEBUG(ErrorF("xg40_Setup(): ulDramType = %02X\n",ulDramType)) ;
151dfe64dd3Smacallan
152dfe64dd3Smacallan    pXGI->BusWidth = (ulMemConfig & (1<<1) )?64:32 ;
153dfe64dd3Smacallan
154dfe64dd3Smacallan    switch(ulMemConfig>>4)
155dfe64dd3Smacallan    {
156dfe64dd3Smacallan    case 8:
157dfe64dd3Smacallan        ulMemSize = 256*1024 ;
158dfe64dd3Smacallan        break ;
159dfe64dd3Smacallan    case 7:
160dfe64dd3Smacallan        ulMemSize = 128*1024 ;
161dfe64dd3Smacallan        break ;
162dfe64dd3Smacallan    case 6:
163dfe64dd3Smacallan        ulMemSize = 64*1024 ;
164dfe64dd3Smacallan        break ;
165dfe64dd3Smacallan    case 5:
166dfe64dd3Smacallan        ulMemSize = 32*1024 ;
167dfe64dd3Smacallan        break ;
168dfe64dd3Smacallan    case 4:
169dfe64dd3Smacallan        ulMemSize = 16*1024 ;
170dfe64dd3Smacallan        break ;
171dfe64dd3Smacallan    case 3:
172dfe64dd3Smacallan        ulMemSize = 8*1024 ;
173dfe64dd3Smacallan        break ;
174dfe64dd3Smacallan    default:
175dfe64dd3Smacallan        ulMemSize = 8*1024 ;
176dfe64dd3Smacallan    }
177dfe64dd3Smacallan
178dfe64dd3Smacallan    if (pXGI->Chipset == PCI_CHIP_XGIXG40) {
179dfe64dd3Smacallan	const unsigned revision =
180dfe64dd3Smacallan#ifdef XSERVER_LIBPCIACCESS
181dfe64dd3Smacallan	    pXGI->PciInfo->revision
182dfe64dd3Smacallan#else
183dfe64dd3Smacallan	    pciReadLong(pXGI->PciTag, 0x08) & 0x0FF
184dfe64dd3Smacallan#endif
185dfe64dd3Smacallan	    ;
186dfe64dd3Smacallan
187dfe64dd3Smacallan	/* Revision 2 cards encode the memory config bits slightly differently
188dfe64dd3Smacallan	 * from revision 1 cards.
189dfe64dd3Smacallan	 */
190dfe64dd3Smacallan        if (revision == 2) {
191dfe64dd3Smacallan            switch((ulMemConfig>>2)&0x1)
192dfe64dd3Smacallan            {
193dfe64dd3Smacallan            case 0:
194dfe64dd3Smacallan                /* Uni channel */
195dfe64dd3Smacallan                ulMemSize *= 1 ;
196dfe64dd3Smacallan       	        break ;
197dfe64dd3Smacallan            case 1:
198dfe64dd3Smacallan                /* Dual channel */
199dfe64dd3Smacallan                ulMemSize *= 2 ;
200dfe64dd3Smacallan    	        break ;
201dfe64dd3Smacallan            }
202dfe64dd3Smacallan        }
203dfe64dd3Smacallan        else
204dfe64dd3Smacallan        {
205dfe64dd3Smacallan            switch((ulMemConfig>>2)&0x3)
206dfe64dd3Smacallan            {
207dfe64dd3Smacallan            case 2:
208dfe64dd3Smacallan                /* Dual channel */
209dfe64dd3Smacallan                ulMemSize *= 2 ;
210dfe64dd3Smacallan        	break ;
211dfe64dd3Smacallan            case 3:
212dfe64dd3Smacallan                /* Quad channel */
213dfe64dd3Smacallan                ulMemSize *= 4 ;
214dfe64dd3Smacallan    	        break ;
215dfe64dd3Smacallan           }
216dfe64dd3Smacallan        }
217dfe64dd3Smacallan    }
218dfe64dd3Smacallan
219dfe64dd3Smacallan    pScrn->videoRam = ulMemSize ;
220dfe64dd3Smacallan
221dfe64dd3Smacallan    /*********************************************************************************************************
222dfe64dd3Smacallan     * SR15 DRAM Address Mapping Register
223dfe64dd3Smacallan     * Default value: XXh
224dfe64dd3Smacallan     *     D7  Channel  interleaving configuration { BChConfig }
225dfe64dd3Smacallan     *         0: Divide the whole memory  into 2/4 equal-sized regions , each mapped to one channel
226dfe64dd3Smacallan     *         1: Divide the whole memory into 2 regions according to BTilingSize[1:0] . The low-address region
227dfe64dd3Smacallan     *         will be channel-interleaved as per BFineGranSize; the high-address region will be channel-
228dfe64dd3Smacallan     *         interleaved  as per BCoarseGranSize[1:0]
229dfe64dd3Smacallan     *     D[6:5]    Memory size of tile-mapped region {BTilingSize}
230dfe64dd3Smacallan     *         00: 4 MB
231dfe64dd3Smacallan     *         01: 8 MB
232dfe64dd3Smacallan     *         10: 16 MB
233dfe64dd3Smacallan     *         11: 32 MB
234dfe64dd3Smacallan     *         The following bits are effective only when D7=1
235dfe64dd3Smacallan     *     D4  Channel-interleaving granularity for tile-mapped region {BFineGranSize}
236dfe64dd3Smacallan     *         0:  64 B
237dfe64dd3Smacallan     *         1:  128 B
238dfe64dd3Smacallan     *     D[3:2] Channel-interleaving granularity for linearly mapped region {BCoarseGranSize}
239dfe64dd3Smacallan     *         00: 1KB
240dfe64dd3Smacallan     *         01: 2KB
241dfe64dd3Smacallan     *         10: 4KB
242dfe64dd3Smacallan     *         11: 1MB
243dfe64dd3Smacallan     *     D[1:0] reserved
244dfe64dd3Smacallan     *********************************************************************************************************/
245dfe64dd3Smacallan
246dfe64dd3Smacallan    /* Accelerator parameter Initialization */
247dfe64dd3Smacallan    if(( pXGI->Chipset == PCI_CHIP_XGIXG20 )||( pXGI->Chipset == PCI_CHIP_XGIXG21 )||( pXGI->Chipset == PCI_CHIP_XGIXG27 ))
248dfe64dd3Smacallan    {
249dfe64dd3Smacallan        pXGI->cmdQueueSize = VOLARI_CQSIZEXG20;
250dfe64dd3Smacallan    /* XgiMode = XG20_Mode ; */
251dfe64dd3Smacallan        PDEBUG(ErrorF(" ---XG20_Mode \n"));
252dfe64dd3Smacallan    }
253dfe64dd3Smacallan
254dfe64dd3Smacallan
255dfe64dd3Smacallan    pXGI->cmdQueueSizeMask = pXGI->cmdQueueSize - 1 ;
256dfe64dd3Smacallan    pXGI->pCQ_shareWritePort = &(pXGI->cmdQueue_shareWP_only2D);
257dfe64dd3Smacallan
258dfe64dd3Smacallan
259dfe64dd3Smacallan    /*
260dfe64dd3Smacallan     If FbDevExist, XFree86 driver use the 8MB only. The rest
261dfe64dd3Smacallan     frame buffer is used by other AP.
262dfe64dd3Smacallan     */
263dfe64dd3Smacallan
264dfe64dd3Smacallan    if( FbDevExist && (pXGI->Chipset != PCI_CHIP_XGIXG20 ) && (pXGI->Chipset != PCI_CHIP_XGIXG21 ) && (pXGI->Chipset != PCI_CHIP_XGIXG27 ) )
265dfe64dd3Smacallan    {
266dfe64dd3Smacallan        if( pScrn->videoRam < 8*1024 )
267dfe64dd3Smacallan        {
268dfe64dd3Smacallan            pXGI->cmdQueueOffset = 4*1024*1024 - pXGI->cmdQueueSize ;
269dfe64dd3Smacallan        }
270dfe64dd3Smacallan        else if( pScrn->videoRam < 16*1024 )
271dfe64dd3Smacallan        {
272dfe64dd3Smacallan            pXGI->cmdQueueOffset = 8*1024*1024 - pXGI->cmdQueueSize ;
273dfe64dd3Smacallan        }
274dfe64dd3Smacallan        else
275dfe64dd3Smacallan        {
276dfe64dd3Smacallan            pXGI->cmdQueueOffset = 13*1024*1024 - pXGI->cmdQueueSize ;
277dfe64dd3Smacallan        }
278dfe64dd3Smacallan    }
279dfe64dd3Smacallan    else
280dfe64dd3Smacallan    {
281dfe64dd3Smacallan        pXGI->cmdQueueOffset = (pScrn->videoRam)*1024 - pXGI->cmdQueueSize ;
282dfe64dd3Smacallan    }
283dfe64dd3Smacallan
284dfe64dd3Smacallan    pXGI->CursorOffset = pXGI->cmdQueueOffset - 64*1024 ;
285dfe64dd3Smacallan    PDEBUG4(ErrorF("pScrn->videoRam = %08lX pXGI->cmdQueueSize = %08lX\n",
286dfe64dd3Smacallan			pScrn->videoRam, pXGI->cmdQueueSize)) ;
287dfe64dd3Smacallan    PDEBUG4(ErrorF("pXGI->cmdQueueOffset = %08lX pXGI->CursorOffset = %08lX\n",
288dfe64dd3Smacallan		pXGI->cmdQueueOffset, pXGI->CursorOffset)) ;
289dfe64dd3Smacallan
290dfe64dd3Smacallan    pXGI->cmdQueueLen = 0 ;
291dfe64dd3Smacallan    pXGI->cmdQueueLenMin = 0x200 ;
292dfe64dd3Smacallan    pXGI->cmdQueueLenMax = pXGI->cmdQueueSize -  pXGI->cmdQueueLenMin ;
293dfe64dd3Smacallan
294dfe64dd3Smacallan    /*****************************************************************
295dfe64dd3Smacallan     * Dual Chip support put here                                    *
296dfe64dd3Smacallan     *****************************************************************/
297dfe64dd3Smacallan    xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
298dfe64dd3Smacallan            "Detected DRAM type : %s\n", dramTypeStr);
299dfe64dd3Smacallan    xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
300dfe64dd3Smacallan            "Detected memory clock : %3.3fMHz\n",
301dfe64dd3Smacallan            pXGI->MemClock/1000.0);
302dfe64dd3Smacallan    xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
303dfe64dd3Smacallan            "Detected VRAM bus width is %d\n", pXGI->BusWidth);
304dfe64dd3Smacallan    xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
305dfe64dd3Smacallan            "Detected Cmd Queue size is %d KB\n", pXGI->cmdQueueSize / 1024);
306dfe64dd3Smacallan    xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
307dfe64dd3Smacallan            "Detected Cmd Queue Offset is %d\n", pXGI->cmdQueueOffset ) ;
308dfe64dd3Smacallan    XGI_InitHwDevInfo(pScrn);
309dfe64dd3Smacallan}
310dfe64dd3Smacallan
311dfe64dd3Smacallanstatic void
312dfe64dd3SmacallanxgiXG40_Setup(ScrnInfoPtr pScrn)
313dfe64dd3Smacallan{
314dfe64dd3Smacallan    static const char *const dramChannelStr[5] = {
315dfe64dd3Smacallan	"<invalid>", "Single", "Dual", "<invalid>", "Quad"
316dfe64dd3Smacallan    };
317dfe64dd3Smacallan
318dfe64dd3Smacallan    static const char *const dramTypeStr[4] = {
319dfe64dd3Smacallan	"DDR SDRAM",
320dfe64dd3Smacallan	"DDR2 SDRAM",
321dfe64dd3Smacallan	"DDR2x SDRAM",
322dfe64dd3Smacallan	""
323dfe64dd3Smacallan    };
324dfe64dd3Smacallan
325dfe64dd3Smacallan/*********************************************************************
326dfe64dd3Smacallan * Setup
327dfe64dd3Smacallan * Decide the following item of execution data:
328dfe64dd3Smacallan *
329dfe64dd3Smacallan * pXGI->BusWidth
330dfe64dd3Smacallan * pXGI->videoRam (with KB unit)
331dfe64dd3Smacallan * pXGI->CursorOffset (with Byte Unit)
332dfe64dd3Smacallan * pXGI->cmdQueueSize (with Byte Unit)
333dfe64dd3Smacallan * pXGI->cmdQueueSizeMask (with Byte Unit)
334dfe64dd3Smacallan * pXGI->cmdQueueOffset (with Byte Unit)
335dfe64dd3Smacallan * pXGI->cmdQueueLen = 0 ; // init value
336dfe64dd3Smacallan * pXGI->cmdQueueLenMin = 0x200 ; // init value
337dfe64dd3Smacallan * pXGI->cmdQueueLenMax = pXGI->cmdQueueSize -  pXGI->cmdQueueLenMin ;
338dfe64dd3Smacallan *********************************************************************/
339dfe64dd3Smacallan
340dfe64dd3Smacallan    XGIPtr        pXGI = XGIPTR(pScrn);
341dfe64dd3Smacallan    unsigned int  ulMemConfig = 0;
342dfe64dd3Smacallan    unsigned mem_per_channel;
343dfe64dd3Smacallan    unsigned mem_channels = 1;
344dfe64dd3Smacallan    unsigned long ulDramType  = 0;
345dfe64dd3Smacallan
346dfe64dd3Smacallan    PDEBUG4(ErrorF("xgiXG40_Setup()\n")) ;
347dfe64dd3Smacallan
348dfe64dd3Smacallan    pXGI->MemClock = XG40Mclk(pXGI);
349dfe64dd3Smacallan
350dfe64dd3Smacallan    /* SR14 DRAM Size Register
351dfe64dd3Smacallan     *     Default value: XXh
352dfe64dd3Smacallan     *     D[7:4]    Memory size per channel {BChMemSize}
353dfe64dd3Smacallan     *         0011: 8 MB
354dfe64dd3Smacallan     *         0100: 16 MB
355dfe64dd3Smacallan     *         0101: 32 MB
356dfe64dd3Smacallan     *         0110: 64 MB
357dfe64dd3Smacallan     *         0111: 128 MB
358dfe64dd3Smacallan     *         1000: 256MB
359dfe64dd3Smacallan     *        others: reserved
360dfe64dd3Smacallan     *     D[3:2]    Number of  dram channels [1:0] {BChNum}
361dfe64dd3Smacallan     *         00: uni-channel
362dfe64dd3Smacallan     *         01: reserved
363dfe64dd3Smacallan     *         10: dual-channel
364dfe64dd3Smacallan     *         11: quad-channel
365dfe64dd3Smacallan     *     D1  Data width per channel selection {BDataWidth}
366dfe64dd3Smacallan     *         0: 32-bits
367dfe64dd3Smacallan     *         1: 64-bits
368dfe64dd3Smacallan     *     D0  Dram channel mapping {BReverseChMapping}
369dfe64dd3Smacallan     *         0: Normal mapping
370dfe64dd3Smacallan     *         1: Reversal mapping
371dfe64dd3Smacallan     *             Dual-channel: Logical channel A/B to physical channel B/A
372dfe64dd3Smacallan     *             Quad-channel: Logical channel A/B/C/D to physical channel
373dfe64dd3Smacallan     *                           C/D/A/B
374dfe64dd3Smacallan     */
375dfe64dd3Smacallan
376dfe64dd3Smacallan    outXGIIDXREG(XGISR, 0x5, 0x86) ;
377dfe64dd3Smacallan    inXGIIDXREG(XGISR, 0x14, ulMemConfig) ;
378dfe64dd3Smacallan
379dfe64dd3Smacallan    /* FIXME: Is this correct?  The SiS driver detects this differently
380dfe64dd3Smacallan     * FIXME: for XG20.
381dfe64dd3Smacallan     */
382dfe64dd3Smacallan    inXGIIDXREG(XGISR, 0x3A, ulDramType) ;
383dfe64dd3Smacallan
384dfe64dd3Smacallan    PDEBUG(ErrorF("xg40_Setup(): ulMemConfig = %02X\n",ulMemConfig)) ;
385dfe64dd3Smacallan    PDEBUG(ErrorF("xg40_Setup(): ulDramType = %02X\n",ulDramType)) ;
386dfe64dd3Smacallan
387dfe64dd3Smacallan    /* FIXME: Is this correct?  The SiS driver detects this differently
388dfe64dd3Smacallan     * FIXME: for XG20.
389dfe64dd3Smacallan     */
390dfe64dd3Smacallan    pXGI->BusWidth = (ulMemConfig & 0x02) ? 64 : 32;
391dfe64dd3Smacallan
392dfe64dd3Smacallan    mem_per_channel = ((ulMemConfig >> 4) >= 3)
393dfe64dd3Smacallan        ? (1 << (ulMemConfig >> 4)) * 1024
394dfe64dd3Smacallan        : 8 * 1024;
395dfe64dd3Smacallan
396dfe64dd3Smacallan
397dfe64dd3Smacallan    /* All XG20 family chips are single channel, so only test the channel
398dfe64dd3Smacallan     * count field on XG40 family chips.
399dfe64dd3Smacallan     */
400dfe64dd3Smacallan    if (pXGI->Chipset == PCI_CHIP_XGIXG40) {
401dfe64dd3Smacallan        /* Check the PCI revision field.  For whatever reason, rev. 2 XG40
402dfe64dd3Smacallan         * chips encode the DRAM channel count differently than other
403dfe64dd3Smacallan         * revisions.
404dfe64dd3Smacallan         */
405dfe64dd3Smacallan        if (pXGI->ChipRev == 2) {
406dfe64dd3Smacallan            switch ((ulMemConfig >> 2) & 0x1) {
407dfe64dd3Smacallan            case 1:
408dfe64dd3Smacallan                /* Dual channel */
409dfe64dd3Smacallan                mem_channels = 2;
410dfe64dd3Smacallan                break ;
411dfe64dd3Smacallan            }
412dfe64dd3Smacallan        }
413dfe64dd3Smacallan        else {
414dfe64dd3Smacallan            switch ((ulMemConfig >> 2) & 0x3) {
415dfe64dd3Smacallan            case 2:
416dfe64dd3Smacallan                /* Dual channel */
417dfe64dd3Smacallan                mem_channels = 2;
418dfe64dd3Smacallan                break ;
419dfe64dd3Smacallan            case 3:
420dfe64dd3Smacallan                /* Quad channel */
421dfe64dd3Smacallan                mem_channels = 4;
422dfe64dd3Smacallan                break ;
423dfe64dd3Smacallan            }
424dfe64dd3Smacallan        }
425dfe64dd3Smacallan    }
426dfe64dd3Smacallan
427dfe64dd3Smacallan    pScrn->videoRam = mem_per_channel * mem_channels;
428dfe64dd3Smacallan
429dfe64dd3Smacallan    /* SR15 DRAM Address Mapping Register
430dfe64dd3Smacallan     * Default value: XXh
431dfe64dd3Smacallan     *     D7  Channel  interleaving configuration { BChConfig }
432dfe64dd3Smacallan     *         0: Divide the whole memory  into 2/4 equal-sized regions , each mapped to one channel
433dfe64dd3Smacallan     *         1: Divide the whole memory into 2 regions according to BTilingSize[1:0] . The low-address region
434dfe64dd3Smacallan     *         will be channel-interleaved as per BFineGranSize; the high-address region will be channel-
435dfe64dd3Smacallan     *         interleaved  as per BCoarseGranSize[1:0]
436dfe64dd3Smacallan     *     D[6:5]    Memory size of tile-mapped region {BTilingSize}
437dfe64dd3Smacallan     *         00: 4 MB
438dfe64dd3Smacallan     *         01: 8 MB
439dfe64dd3Smacallan     *         10: 16 MB
440dfe64dd3Smacallan     *         11: 32 MB
441dfe64dd3Smacallan     *         The following bits are effective only when D7=1
442dfe64dd3Smacallan     *     D4  Channel-interleaving granularity for tile-mapped region {BFineGranSize}
443dfe64dd3Smacallan     *         0:  64 B
444dfe64dd3Smacallan     *         1:  128 B
445dfe64dd3Smacallan     *     D[3:2] Channel-interleaving granularity for linearly mapped region {BCoarseGranSize}
446dfe64dd3Smacallan     *         00: 1KB
447dfe64dd3Smacallan     *         01: 2KB
448dfe64dd3Smacallan     *         10: 4KB
449dfe64dd3Smacallan     *         11: 1MB
450dfe64dd3Smacallan     *     D[1:0] reserved
451dfe64dd3Smacallan     */
452dfe64dd3Smacallan
453dfe64dd3Smacallan    /* Accelerator parameter Initialization */
454dfe64dd3Smacallan
455dfe64dd3Smacallan    pXGI->cmdQueueSize = ((pXGI->Chipset == PCI_CHIP_XGIXG20)||(pXGI->Chipset == PCI_CHIP_XGIXG21||(pXGI->Chipset == PCI_CHIP_XGIXG27)))
456dfe64dd3Smacallan	? VOLARI_CQSIZEXG20 : VOLARI_CQSIZE;
457dfe64dd3Smacallan    pXGI->cmdQueueSizeMask = pXGI->cmdQueueSize - 1 ;
458dfe64dd3Smacallan    pXGI->pCQ_shareWritePort = &(pXGI->cmdQueue_shareWP_only2D);
459dfe64dd3Smacallan
460dfe64dd3Smacallan
461dfe64dd3Smacallan    /* If FbDevExist, X.org driver uses 8MB only. The rest of the framebuffer
462dfe64dd3Smacallan     * is used by the fbdev driver.
463dfe64dd3Smacallan     */
464dfe64dd3Smacallan    if (FbDevExist) {
465dfe64dd3Smacallan	/* FIXME: Is it even possible to have less than 8Mb of video memory?
466dfe64dd3Smacallan	 */
467dfe64dd3Smacallan        if (pScrn->videoRam < 8*1024) {
468dfe64dd3Smacallan            pXGI->cmdQueueOffset = 4*1024*1024 - pXGI->cmdQueueSize;
469dfe64dd3Smacallan        }
470dfe64dd3Smacallan	else if (pScrn->videoRam < 16*1024) {
471dfe64dd3Smacallan	    pXGI->cmdQueueOffset = 8*1024*1024 - pXGI->cmdQueueSize;
472dfe64dd3Smacallan	}
473dfe64dd3Smacallan        else {
474dfe64dd3Smacallan            pXGI->cmdQueueOffset = 13*1024*1024 - pXGI->cmdQueueSize;
475dfe64dd3Smacallan        }
476dfe64dd3Smacallan    }
477dfe64dd3Smacallan    else {
478dfe64dd3Smacallan        pXGI->cmdQueueOffset = (pScrn->videoRam)*1024 - pXGI->cmdQueueSize;
479dfe64dd3Smacallan    }
480dfe64dd3Smacallan
481dfe64dd3Smacallan    pXGI->CursorOffset = pXGI->cmdQueueOffset - 64*1024;
482dfe64dd3Smacallan    PDEBUG4(ErrorF("pScrn->videoRam = %08lX pXGI->cmdQueueSize = %08lX\n",
483dfe64dd3Smacallan			pScrn->videoRam, pXGI->cmdQueueSize)) ;
484dfe64dd3Smacallan    PDEBUG4(ErrorF("pXGI->cmdQueueOffset = %08lX pXGI->CursorOffset = %08lX\n",
485dfe64dd3Smacallan		pXGI->cmdQueueOffset, pXGI->CursorOffset)) ;
486dfe64dd3Smacallan
487dfe64dd3Smacallan    pXGI->cmdQueueLen = 0 ;
488dfe64dd3Smacallan    pXGI->cmdQueueLenMin = 0x200 ;
489dfe64dd3Smacallan    pXGI->cmdQueueLenMax = pXGI->cmdQueueSize -  pXGI->cmdQueueLenMin ;
490dfe64dd3Smacallan
491dfe64dd3Smacallan    /* Dual Chip support put here
492dfe64dd3Smacallan     */
493dfe64dd3Smacallan    xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
494dfe64dd3Smacallan	       "Detected DRAM type : %s channel %s\n",
495dfe64dd3Smacallan	       dramChannelStr[mem_channels],
496dfe64dd3Smacallan	       dramTypeStr[(ulDramType & 0x02) >> 1]);
497dfe64dd3Smacallan    xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
498dfe64dd3Smacallan            "Detected memory clock : %3.3fMHz\n",
499dfe64dd3Smacallan            pXGI->MemClock/1000.0);
500dfe64dd3Smacallan    xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
501dfe64dd3Smacallan            "Detected VRAM bus width is %d\n", pXGI->BusWidth);
502dfe64dd3Smacallan    xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
503dfe64dd3Smacallan            "Detected Cmd Queue size is %d KB\n", pXGI->cmdQueueSize / 1024);
504dfe64dd3Smacallan    xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
505dfe64dd3Smacallan            "Detected Cmd Queue Offset is %d\n", pXGI->cmdQueueOffset ) ;
506dfe64dd3Smacallan    XGI_InitHwDevInfo(pScrn);
507dfe64dd3Smacallan}
508dfe64dd3Smacallan
509dfe64dd3Smacallanvoid
510dfe64dd3SmacallanXGISetup(ScrnInfoPtr pScrn)
511dfe64dd3Smacallan{
512dfe64dd3Smacallan    XGIPtr pXGI = XGIPTR(pScrn);
513dfe64dd3Smacallan
514dfe64dd3Smacallan    pXGI->Flags = 0;
515dfe64dd3Smacallan    pXGI->VBFlags = 0;
516dfe64dd3Smacallan
517dfe64dd3Smacallan	/* Jong 10/16/2007; merge code */
518dfe64dd3Smacallan    switch (pXGI->Chipset) {
519dfe64dd3Smacallan		case PCI_CHIP_XGIXG20:
520dfe64dd3Smacallan		case PCI_CHIP_XGIXG21:
521dfe64dd3Smacallan		case PCI_CHIP_XGIXG27:
522dfe64dd3Smacallan			xgiXG2X_Setup(pScrn);
523dfe64dd3Smacallan			break;
524dfe64dd3Smacallan
525dfe64dd3Smacallan		case PCI_CHIP_XGIXG40:
526dfe64dd3Smacallan		default:
527dfe64dd3Smacallan			xgiXG40_Setup(pScrn);
528dfe64dd3Smacallan			break;
529dfe64dd3Smacallan    }
530dfe64dd3Smacallan}
531dfe64dd3Smacallan
532dfe64dd3Smacallan/* Jong 01/07/2008; Force to disable 2D engine by SR3A[6]=1 */
533dfe64dd3SmacallanBool ForceToDisable2DEngine(ScrnInfoPtr pScrn)
534dfe64dd3Smacallan{
535dfe64dd3Smacallan    XGIPtr pXGI ;
536dfe64dd3Smacallan	Bool   bReturn=FALSE;
537dfe64dd3Smacallan    CARD8  bForce;
538dfe64dd3Smacallan
539dfe64dd3Smacallan    pXGI = XGIPTR(pScrn);
540dfe64dd3Smacallan
541dfe64dd3Smacallan	if(pXGI->Chipset == PCI_CHIP_XGIXG21)
542dfe64dd3Smacallan	{
543dfe64dd3Smacallan	    inXGIIDXREG(XGISR, 0x3A, bForce) ;
544dfe64dd3Smacallan		bForce &= 0x40;
545dfe64dd3Smacallan
546dfe64dd3Smacallan		if(bForce == 0)
547dfe64dd3Smacallan			bReturn=FALSE;
548dfe64dd3Smacallan		else
549dfe64dd3Smacallan			bReturn=TRUE;
550dfe64dd3Smacallan	}
551dfe64dd3Smacallan	else
552dfe64dd3Smacallan	{
553dfe64dd3Smacallan		bReturn=FALSE;
554dfe64dd3Smacallan	}
555dfe64dd3Smacallan
556dfe64dd3Smacallan	return(bReturn);
557dfe64dd3Smacallan}
558dfe64dd3Smacallan
559dfe64dd3SmacallanBool
560dfe64dd3SmacallanXGI_IsXG21(ScrnInfoPtr pScrn)
561dfe64dd3Smacallan{
562dfe64dd3Smacallan    XGIPtr pXGI = XGIPTR(pScrn);
563dfe64dd3Smacallan    Bool is_XG21 = FALSE;
564dfe64dd3Smacallan
565dfe64dd3Smacallan    if (pXGI->Chipset == PCI_CHIP_XGIXG20) {
566dfe64dd3Smacallan		int temp;
567dfe64dd3Smacallan
568dfe64dd3Smacallan        orXGIIDXREG(XGICR, Index_CR_GPIO_Reg3, GPIOG_EN);
569dfe64dd3Smacallan        inXGIIDXREG(XGICR, Index_CR_GPIO_Reg1, temp);
570dfe64dd3Smacallan
571dfe64dd3Smacallan		is_XG21 = ((temp & GPIOG_READ) != 0);
572dfe64dd3Smacallan    }
573dfe64dd3Smacallan
574dfe64dd3Smacallan    return is_XG21;
575dfe64dd3Smacallan}
576dfe64dd3Smacallan
577dfe64dd3Smacallanvoid
578dfe64dd3SmacallanXGI_InitHwDevInfo(ScrnInfoPtr pScrn)
579dfe64dd3Smacallan{
580dfe64dd3Smacallan    XGIPtr pXGI = XGIPTR(pScrn);
581dfe64dd3Smacallan    PXGI_HW_DEVICE_INFO pHwDevInfo = &pXGI->xgi_HwDevExt;
582dfe64dd3Smacallan    int i;
583dfe64dd3Smacallan
584dfe64dd3Smacallan    pHwDevInfo->pDevice = pXGI ;
585dfe64dd3Smacallan    pHwDevInfo->pjVirtualRomBase = pXGI->BIOS ;
586dfe64dd3Smacallan    pHwDevInfo->pjCustomizedROMImage = NULL ;
587dfe64dd3Smacallan    pHwDevInfo->pjVideoMemoryAddress = (UCHAR*)(pXGI->FbBase) ;
588dfe64dd3Smacallan    PDEBUG(ErrorF("pXGI->FbBase = 0x%08lx\n",(ULONG)(pXGI->FbBase))) ;
589dfe64dd3Smacallan    PDEBUG(ErrorF("pHwDevInfo->pjVideoMemoryAddress = 0x%08lx\n",(ULONG)(pHwDevInfo->pjVideoMemoryAddress))) ;
590dfe64dd3Smacallan    pHwDevInfo->ulVideoMemorySize = pXGI->FbMapSize ;
591dfe64dd3Smacallan    pHwDevInfo->pjIOAddress = pXGI->RelIO + 0x30 ;
592dfe64dd3Smacallan
593dfe64dd3Smacallan    switch (pXGI->Chipset) {
594dfe64dd3Smacallan    case PCI_CHIP_XGIXG40:
595dfe64dd3Smacallan        pHwDevInfo->jChipType = XG40 ;
596dfe64dd3Smacallan        break ;
597dfe64dd3Smacallan    case PCI_CHIP_XGIXG20:
598dfe64dd3Smacallan        pHwDevInfo->jChipType = XGI_IsXG21(pScrn)?XG21:XG20 ;
599dfe64dd3Smacallan        break ;
600dfe64dd3Smacallan    case PCI_CHIP_XGIXG27:
601dfe64dd3Smacallan    pHwDevInfo->jChipType = XG27;
602dfe64dd3Smacallan        break;
603dfe64dd3Smacallan    case PCI_CHIP_XGIXG21:
604dfe64dd3Smacallan	pHwDevInfo->jChipType = XG21;
605dfe64dd3Smacallan	break;
606dfe64dd3Smacallan    default:
607dfe64dd3Smacallan        pHwDevInfo->jChipType = XG40 ;
608dfe64dd3Smacallan        break ;
609dfe64dd3Smacallan    }
610dfe64dd3Smacallan
611dfe64dd3Smacallan    pHwDevInfo->jChipRevision = pXGI->ChipRev;
612dfe64dd3Smacallan    pHwDevInfo->ujVBChipID = VB_CHIP_UNKNOWN ;
613dfe64dd3Smacallan    pHwDevInfo->ulExternalChip = 0 ;
614dfe64dd3Smacallan
615dfe64dd3Smacallan    pHwDevInfo->ulCRT2LCDType = LCD_1024x768 ;
616dfe64dd3Smacallan    pHwDevInfo->bIntegratedMMEnabled = FALSE ;
617dfe64dd3Smacallan    pHwDevInfo->bSkipDramSizing = TRUE ;
618dfe64dd3Smacallan
619dfe64dd3Smacallan    pHwDevInfo->pSR = pXGI->SRList ;
620dfe64dd3Smacallan    pHwDevInfo->pCR = pXGI->CRList ;
621dfe64dd3Smacallan    pHwDevInfo->pQueryVGAConfigSpace = (PXGI_QUERYSPACE) bAccessVGAPCIInfo;
622dfe64dd3Smacallan
623dfe64dd3Smacallan    for( i = 0 ; i < ExtRegSize ; i++ ){
624dfe64dd3Smacallan        pHwDevInfo->pSR[i].jIdx = 0xFF ;
625dfe64dd3Smacallan        pHwDevInfo->pSR[i].jVal = 0xFF ;
626dfe64dd3Smacallan        pHwDevInfo->pCR[i].jIdx = 0xFF ;
627dfe64dd3Smacallan        pHwDevInfo->pCR[i].jVal = 0xFF ;
628dfe64dd3Smacallan    }
629dfe64dd3Smacallan
630dfe64dd3Smacallan    for( i = 0 ; i < VBIOS_VER_MAX_LENGTH ; i++ ){
631dfe64dd3Smacallan        pHwDevInfo -> szVBIOSVer[i] = '\0' ;
632dfe64dd3Smacallan    }
633dfe64dd3Smacallan
634dfe64dd3Smacallan
635dfe64dd3Smacallan    XGINew_InitVBIOSData(pHwDevInfo, pXGI->XGI_Pr);
636dfe64dd3Smacallan    PDEBUG(ErrorF("XGINew_InitVBIOSData(pHwDevInfo) done\n")) ;
637dfe64dd3Smacallan
638dfe64dd3Smacallan    ErrorF("XGI_InitVBIOSData  VBType = %x\n", pXGI->XGI_Pr->VBType);
639dfe64dd3Smacallan    XGI_New_GetVBType(pXGI->XGI_Pr, pHwDevInfo); //yilin
640dfe64dd3Smacallan    ErrorF("XGI_New_GetVBType  VBType = %x\n", pXGI->XGI_Pr->VBType);
641dfe64dd3Smacallan
642dfe64dd3Smacallan //   pHwDevInfo->ujVBChipID = VB_CHIP_301 ; //yilin
643dfe64dd3Smacallan    if( pXGI->XGI_Pr->VBType & (VB_XGI301 | VB_XGI301B | VB_XGI301C))
644dfe64dd3Smacallan    {
645dfe64dd3Smacallan    PDEBUG(ErrorF("VB chip = 301 \n")) ;
646dfe64dd3Smacallan	 pHwDevInfo->ujVBChipID = VB_CHIP_301 ;
647dfe64dd3Smacallan    }
648dfe64dd3Smacallan    else if( pXGI->VBFlags & ( VB_XGI302B| VB_XGI302LV ))
649dfe64dd3Smacallan    {
650dfe64dd3Smacallan        pHwDevInfo->ujVBChipID = VB_CHIP_302 ;
651dfe64dd3Smacallan    }
652dfe64dd3Smacallan/*
653dfe64dd3Smacallan    else if (pXGI->VBFlags & VB_LVDS) {
654dfe64dd3Smacallan        pHwDevInfo->ulExternalChip |= 0x01 ;
655dfe64dd3Smacallan    }
656dfe64dd3Smacallan*/ //yilin
657dfe64dd3Smacallan
658dfe64dd3Smacallan
659dfe64dd3Smacallan    PDEBUG(ErrorF("pHwDevInfo->jChipType = %08lX done\n",pHwDevInfo->jChipType)) ;
660dfe64dd3Smacallan}
661dfe64dd3Smacallan
662dfe64dd3SmacallanBool
663098ad5bdSmacallanbAccessVGAPCIInfo(PXGI_HW_DEVICE_INFO pHwDevInfo, ULONG ulOffset, ULONG ulSet, CARD32 *pulValue)
664dfe64dd3Smacallan{
665dfe64dd3Smacallan    XGIPtr pXGI ;
666dfe64dd3Smacallan#ifdef XSERVER_LIBPCIACCESS
667dfe64dd3Smacallan    int err;
668dfe64dd3Smacallan#else
669dfe64dd3Smacallan    PCITAG pciDev;
670dfe64dd3Smacallan#endif
671dfe64dd3Smacallan
672dfe64dd3Smacallan    if (!pHwDevInfo || !pulValue) {
673dfe64dd3Smacallan        return FALSE;
674dfe64dd3Smacallan    }
675dfe64dd3Smacallan
676dfe64dd3Smacallan    pXGI = (XGIPtr)pHwDevInfo->pDevice ;
677dfe64dd3Smacallan#ifdef XSERVER_LIBPCIACCESS
678dfe64dd3Smacallan    if (ulSet) {
679dfe64dd3Smacallan	err = pci_device_cfg_write_u32(pXGI->PciInfo, *pulValue,
680dfe64dd3Smacallan				       ulOffset & ~3);
681dfe64dd3Smacallan    } else {
682cb1acafbSmacallan	err = pci_device_cfg_read_u32(pXGI->PciInfo, (uint32_t *)pulValue,
683dfe64dd3Smacallan				       ulOffset & ~3);
684dfe64dd3Smacallan    }
685dfe64dd3Smacallan
686dfe64dd3Smacallan    return (err == 0);
687dfe64dd3Smacallan#else
688dfe64dd3Smacallan    pciDev = pXGI->PciTag ;
689dfe64dd3Smacallan
690dfe64dd3Smacallan    if (ulSet) {
691dfe64dd3Smacallan        pciWriteLong(pciDev, ulOffset&0xFFFFFFFc, *pulValue);
692dfe64dd3Smacallan    } else {
693dfe64dd3Smacallan        *pulValue = pciReadLong(pciDev, ulOffset&0xFFFFFFFc);
694dfe64dd3Smacallan    }
695dfe64dd3Smacallan
696dfe64dd3Smacallan    return TRUE ;
697dfe64dd3Smacallan#endif
698dfe64dd3Smacallan}
699