savage_accel.c revision ab47cfaa
1/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/savage/savage_accel.c,v 1.23 2003/12/22 17:48:10 tsi Exp $ */
2
3/*
4 *
5 * Copyright 1995-1997 The XFree86 Project, Inc.
6 *
7 */
8
9/*
10 * The accel file for the Savage driver.
11 *
12 * Created 20/03/97 by Sebastien Marineau for 3.3.6
13 * Modified 17-Nov-2000 by Tim Roberts for 4.0.1
14 * Modified Feb-2004 by Alex Deucher - integrating DRI support
15 * Revision:
16 *
17 */
18
19#ifdef HAVE_CONFIG_H
20#include "config.h"
21#endif
22
23#include "savage_driver.h"
24#include "savage_regs.h"
25#include "savage_bci.h"
26#include "savage_streams.h"
27
28#ifdef XF86DRI
29#define _XF86DRI_SERVER_
30#include "savage_dri.h"
31#endif
32
33extern int gSavageEntityIndex;
34
35/* Forward declaration of functions used in the driver */
36
37unsigned long writedw( unsigned long addr, unsigned long value );
38unsigned long readdw( unsigned long addr );
39unsigned long readfb( unsigned long addr );
40unsigned long writefb( unsigned long addr, unsigned long value );
41void writescan( unsigned long scan, unsigned long color );
42
43static int GetTileAperturePitch(unsigned long dwWidth, unsigned long dwBpp);
44void SavageSetGBD_M7(ScrnInfoPtr pScrn);
45void SavageSetGBD_3D(ScrnInfoPtr pScrn);
46void SavageSetGBD_Twister(ScrnInfoPtr pScrn);
47void SavageSetGBD_PM(ScrnInfoPtr pScrn);
48void SavageSetGBD_2000(ScrnInfoPtr pScrn);
49
50/*
51 * This is used to cache the last known value for routines we want to
52 * call from the debugger.
53 */
54
55ScrnInfoPtr gpScrn = 0;
56
57/*
58 *  returns the aperture pitch for tiled mode.
59 *  if MM850C_15 = 0 (use NB linear tile mode) the pitch is screen stride aligned to 128bytes
60 *  if MM850C_15 = 1 (use MS-1 128bit non-linear tile mode),we should do it as follows
61 *  we now only support the later, and don't use Y range flag,see tile surface register
62*/
63static int GetTileAperturePitch(unsigned long dwWidth, unsigned long dwBpp)
64{
65    switch (dwBpp) {
66        case 4:
67        case 8:
68            return(0x2000);
69            break;
70        case 16:
71            return(0x1000);
72            break;
73        case 32:
74            return(0x2000);
75            break;
76        default:
77            return(0x2000);
78    }
79}
80
81static int GetTileAperturePitch2000(unsigned long dwWidth, unsigned long dwBpp, int lDelta)
82{
83    switch (dwBpp) {
84        case 4:
85        case 8:
86            return(0x2000);
87            break;
88        case 16:
89	    if (lDelta > 0x800)
90                return(0x1000);
91	    else
92	        return(0x800);
93            break;
94        case 32:
95	    if (lDelta > 0x1000)
96                return(0x2000);
97	    else
98	        return(0x1000);
99            break;
100        default:
101            return(0x2000);
102    }
103}
104
105void
106SavageInitialize2DEngine(ScrnInfoPtr pScrn)
107{
108    vgaHWPtr hwp = VGAHWPTR(pScrn);
109    SavagePtr psav = SAVPTR(pScrn);
110    unsigned int vgaCRIndex = hwp->IOBase + 4;
111    unsigned int vgaCRReg = hwp->IOBase + 5;
112
113    gpScrn = pScrn;
114
115    VGAOUT16(vgaCRIndex, 0x0140);
116    VGAOUT8(vgaCRIndex, 0x31);
117    VGAOUT8(vgaCRReg, 0x0c);
118
119    /* Setup plane masks */
120    OUTREG(0x8128, ~0); /* enable all write planes */
121    OUTREG(0x812C, ~0); /* enable all read planes */
122    OUTREG16(0x8134, 0x27);
123    OUTREG16(0x8136, 0x07);
124
125    switch( psav->Chipset ) {
126
127    case S3_SAVAGE3D:
128    case S3_SAVAGE_MX:
129	/* Disable BCI */
130	OUTREG(0x48C18, INREG(0x48C18) & 0x3FF0);
131	/* Setup BCI command overflow buffer */
132	OUTREG(0x48C14, (psav->cobOffset >> 11) | (psav->cobIndex << 29)); /* tim */
133    	/*OUTREG(S3_OVERFLOW_BUFFER, psav->cobOffset >> 11 | 0xE0000000);*/ /* S3 */
134	/* Program shadow status update. */
135	{
136	    unsigned long thresholds = ((psav->bciThresholdLo & 0xffff) << 16) |
137		(psav->bciThresholdHi & 0xffff);
138	    OUTREG(0x48C10, thresholds);
139	    /* used to be 0x78207220 */
140	}
141	if( psav->ShadowStatus )
142	{
143	    OUTREG(0x48C0C, psav->ShadowPhysical | 1 );
144	    /* Enable BCI and command overflow buffer */
145	    OUTREG(0x48C18, INREG(0x48C18) | 0x0E);
146	}
147	else
148	{
149	    OUTREG(0x48C0C, 0);
150	    /* Enable BCI and command overflow buffer */
151	    OUTREG(0x48C18, INREG(0x48C18) | 0x0C);
152	}
153	break;
154
155    case S3_SAVAGE4:
156    case S3_TWISTER:
157    case S3_PROSAVAGE:
158    case S3_PROSAVAGEDDR:
159    case S3_SUPERSAVAGE:
160	/* Disable BCI */
161	OUTREG(0x48C18, INREG(0x48C18) & 0x3FF0);
162	if (!psav->disableCOB) {
163	    /* Setup BCI command overflow buffer */
164	    OUTREG(0x48C14, (psav->cobOffset >> 11) | (psav->cobIndex << 29));
165	}
166	/* Program shadow status update */ /* AGD: what should this be? */
167	{
168	    unsigned long thresholds = ((psav->bciThresholdLo & 0x1fffe0) << 11) |
169		((psav->bciThresholdHi & 0x1fffe0) >> 5);
170	    OUTREG(0x48C10, thresholds);
171	}
172	/*OUTREG(0x48C10, 0x00700040);*/ /* tim */
173        /*OUTREG(0x48C10, 0x0e440f04L);*/ /* S3 */
174	if( psav->ShadowStatus )
175	{
176	    OUTREG(0x48C0C, psav->ShadowPhysical | 1 );
177	    if (psav->disableCOB) {
178	    	/* Enable BCI without the COB */
179		OUTREG(0x48C18, INREG(0x48C18) | 0x0a);
180	    } else {
181		OUTREG32(0x48C18, INREG32(0x48C18) | 0x0E);
182	    }
183	}
184	else
185	{
186	    OUTREG(0x48C0C, 0);
187	    if (psav->disableCOB) {
188	    	/* Enable BCI without the COB */
189	    	OUTREG(0x48C18, INREG(0x48C18) | 0x08);
190	    } else {
191		OUTREG32(0x48C18, INREG32(0x48C18) | 0x0C);
192	    }
193	}
194	break;
195
196    case S3_SAVAGE2000:
197	/* Disable BCI */
198	OUTREG(0x48C18, 0);
199	/* Setup BCI command overflow buffer */
200	OUTREG(0x48C18, (psav->cobOffset >> 7) | (psav->cobIndex));
201	if( psav->ShadowStatus )
202	{
203	    /* Set shadow update threshholds. */
204	    /*OUTREG(0x48C10, 0x6090 );
205	      OUTREG(0x48C14, 0x70A8 );*/
206	    OUTREG(0x48C10, psav->bciThresholdLo >> 2);
207	    OUTREG(0x48C14, psav->bciThresholdHi >> 2);
208	    /* Enable shadow status update */
209	    OUTREG(0x48A30, psav->ShadowPhysical );
210	    /* Enable BCI, command overflow buffer and shadow status. */
211	    OUTREG(0x48C18, INREG(0x48C18) | 0x00380000 );
212	}
213	else
214	{
215	    /* Disable shadow status update */
216	    OUTREG(0x48A30, 0);
217	    /* Enable BCI and command overflow buffer */
218	    OUTREG(0x48C18, INREG(0x48C18) | 0x00280000 );
219	}
220	break;
221    }
222
223    /* Use and set global bitmap descriptor. */
224
225    /* For reasons I do not fully understand yet, on the Savage4, the */
226    /* write to the GBD register, MM816C, does not "take" at this time. */
227    /* Only the low-order byte is acknowledged, resulting in an incorrect */
228    /* stride.  Writing the register later, after the mode switch, works */
229    /* correctly.  This needs to get resolved. */
230
231    SavageSetGBD(pScrn);
232}
233
234void
235SavageSetGBD(ScrnInfoPtr pScrn)
236{
237    SavagePtr psav = SAVPTR(pScrn);
238
239    UnProtectCRTC();
240    UnLockExtRegs();
241    VerticalRetraceWait();
242
243    psav->lDelta = pScrn->virtualX * (pScrn->bitsPerPixel >> 3);
244
245    /*
246     * we can use Option "DisableTile" "TRUE" to disable tile mode
247     * if don't disable tile,we only support tile mode under 16/32bpp
248     */
249    if ((!psav->bDisableTile) && ((pScrn->bitsPerPixel == 16) || (pScrn->bitsPerPixel == 32))) {
250        /* tileing in 16/32 BPP */
251        psav->bTiled = TRUE;
252        psav->lDelta = ((psav->lDelta + 127) >> 7) << 7;
253
254        if (S3_SAVAGE3D_SERIES(psav->Chipset))
255            psav->ulAperturePitch = 0x2000;
256	else if (psav->Chipset == S3_SAVAGE2000)
257	    psav->ulAperturePitch = GetTileAperturePitch2000(pScrn->virtualX,
258							     pScrn->bitsPerPixel,
259							     psav->lDelta);
260        else
261            psav->ulAperturePitch = GetTileAperturePitch(pScrn->virtualX,pScrn->bitsPerPixel);
262
263        /* Use the aperture for linear screen */
264        psav->FBStart = psav->ApertureMap;
265    } else {
266        psav->bTiled = FALSE;
267        /* 32: Alignment for nontiled mode */
268        psav->lDelta = ((psav->lDelta + 31) >> 5) << 5;
269        psav->ulAperturePitch = psav->lDelta;
270    }
271
272    psav->Bpp = pScrn->bitsPerPixel >> 3;
273    psav->cxMemory = psav->lDelta / (psav->Bpp);
274    psav->cyMemory = psav->endfb / psav->lDelta - 1;
275    /* ??????????? */
276    if (psav->cyMemory > 2048)
277        psav->cyMemory = 2048;
278
279    /*
280     * If tiling, adjust down psav->cyMemory to the last multiple
281     * of a tileheight, so that we don't try to use partial tiles.
282     */
283    if (psav->bTiled)  {
284        psav->cyMemory -= (psav->cyMemory % 16);
285    }
286
287    /*
288     *  Initialization per GX-3.
289     *
290     *  1. MM48C18 - Disable BCI.
291     *  2. MM48C0C - Enable updating shadow status
292     *              and initialize shadow memory address.
293     *  2b. MM48C18 - bit 1 = 1, Enable Command Buffer status updates
294     *              (S3_OVERFLOW_BUFFER_PTR)
295     *  3. MM48C10 - Initialize command buffer threshold
296     *              (S3_BUFFER_THRESHOLD)
297     *  4. MM48C14 - Setup command buffer offset and size
298     *              (S3_OVERFLOW_BUFFER)
299     *  5. MM816C  - Enable BCI.
300     *  6. MM48C40 - Setup tiled surface 0 register.
301     *  7. CR31 - bit 0 = 0, Disable address offset bits(CR6A_6-0).
302     *  8. CR50 - bit 7,6,0 = 111, Use Global Bitmap Descriptor.
303     *  9. CR88 - bit 4 = 0, Block write on (linear mode) IFF we know we
304     *                       have the right kind of SGRAM memory,
305     *                       bit 4 = 1, Block write off (always off if tiling)
306     *  10.CR69 - Bit 7 = 1, MM81C0 and 81C4 are used to control
307     *                       primary stream.
308     *  11.MM8128, MM812c - Setup read/write mask registers
309     *  12.MM816C, MM8168 - Set up Global Bitmap Descriptor 1 and 2.
310     */
311    switch (psav->Chipset) {
312        case S3_SAVAGE3D:
313	    SavageSetGBD_3D(pScrn);
314	    break;
315        case S3_SAVAGE_MX:
316            SavageSetGBD_M7(pScrn);
317            break;
318        case S3_SAVAGE4:
319        case S3_TWISTER:
320        case S3_PROSAVAGE:
321        case S3_PROSAVAGEDDR:
322            SavageSetGBD_Twister(pScrn);
323            break;
324        case S3_SUPERSAVAGE:
325            SavageSetGBD_PM(pScrn);
326            break;
327        case S3_SAVAGE2000:
328	    SavageSetGBD_2000(pScrn);
329	    break;
330    }
331}
332
333void SavageSetGBD_Twister(ScrnInfoPtr pScrn)
334{
335    SavagePtr psav = SAVPTR(pScrn);
336    unsigned long       ulTmp;
337    unsigned char byte;
338    int bci_enable, tile16, tile32;
339
340    if (psav->Chipset == S3_SAVAGE4) {
341	bci_enable = BCI_ENABLE;
342	tile16 = TILE_FORMAT_16BPP;
343	tile32 = TILE_FORMAT_32BPP;
344    } else {
345	bci_enable = BCI_ENABLE_TWISTER;
346	tile16 = TILE_DESTINATION;
347	tile32 = TILE_DESTINATION;
348    }
349
350    /* MM81C0 and 81C4 are used to control primary stream. */
351    OUTREG32(PSTREAM_FBADDR0_REG,0x00000000);
352    OUTREG32(PSTREAM_FBADDR1_REG,0x00000000);
353
354    /*
355     *  Program Primary Stream Stride Register.
356     *
357     *  Tell engine if tiling on or off, set primary stream stride, and
358     *  if tiling, set tiling bits/pixel and primary stream tile offset.
359     *  Note that tile offset (bits 16 - 29) must be scanline width in
360     *  bytes/128bytespertile * 256 Qwords/tile.  This is equivalent to
361     *  lDelta * 2.  Remember that if tiling, lDelta is screenwidth in
362     *  bytes padded up to an even number of tilewidths.
363     */
364    if (!psav->bTiled) {
365        OUTREG32(PSTREAM_STRIDE_REG,
366                 (((psav->lDelta * 2) << 16) & 0x3FFFE000) |
367                 (psav->lDelta & 0x00001fff));
368    }
369    else if (pScrn->bitsPerPixel == 16) {
370        /* Scanline-length-in-bytes/128-bytes-per-tile * 256 Qwords/tile */
371        OUTREG32(PSTREAM_STRIDE_REG,
372                 (((psav->lDelta * 2) << 16) & 0x3FFFE000)
373                 | 0x80000000 | (psav->lDelta & 0x00001fff));
374    }
375    else if (pScrn->bitsPerPixel == 32) {
376        OUTREG32(PSTREAM_STRIDE_REG,
377                 (((psav->lDelta * 2) << 16) & 0x3FFFE000)
378                 | 0xC0000000 | (psav->lDelta & 0x00001fff));
379    }
380
381    /*
382     *  CR69, bit 7 = 1
383     *  to use MM streams processor registers to control primary stream.
384     */
385    OUTREG8(CRT_ADDRESS_REG,0x69);
386    byte = INREG8(CRT_DATA_REG) | 0x80;
387    OUTREG8(CRT_DATA_REG,byte);
388
389    OUTREG32(0x8128, 0xFFFFFFFFL);
390    OUTREG32(0x812C, 0xFFFFFFFFL);
391
392    OUTREG32(S3_BCI_GLB_BD_HIGH, bci_enable | S3_LITTLE_ENDIAN | S3_BD64);
393
394
395    /* CR50, bit 7,6,0 = 111, Use GBD.*/
396    OUTREG8(CRT_ADDRESS_REG,0x50);
397    byte = INREG8(CRT_DATA_REG) | 0xC1;
398    OUTREG8(CRT_DATA_REG, byte);
399
400    /*
401     * if MS1NB style linear tiling mode.
402     * bit MM850C[15] = 0 select NB linear tile mode.
403     * bit MM850C[15] = 1 select MS-1 128-bit non-linear tile mode.
404     */
405    ulTmp = INREG32(ADVANCED_FUNC_CTRL) | 0x8000; /* use MS-s style tile mode*/
406    OUTREG32(ADVANCED_FUNC_CTRL,ulTmp);
407
408    /*
409     * Set up Tiled Surface Registers
410     *  Bit 25:20 - Surface width in tiles.
411     *  Bit 29 - Y Range Flag.
412     *  Bit 31:30 = 00, 4 bpp.
413     *            = 01, 8 bpp.
414     *            = 10, 16 bpp.
415     *            = 11, 32 bpp.
416     */
417    /*
418     * Global Bitmap Descriptor Register MM816C - twister/prosavage
419     *   bit 24~25: tile format
420     *          00: linear
421     *          01: destination tiling format
422     *          10: texture tiling format
423     *          11: reserved
424     *   bit 28: block write disble/enable
425     *          0: disable
426     *          1: enable
427     */
428    /*
429     * Global Bitmap Descriptor Register MM816C - savage4
430     *   bit 24~25: tile format
431     *          00: linear
432     *          01: reserved
433     *          10: 16 bpp tiles
434     *          11: 32 bpp tiles
435     *   bit 28: block write disable/enable
436     *          0: enable
437     *          1: disable
438     */
439    if (!psav->bTiled) {
440        /*
441         *  Do not enable block_write even for non-tiling modes, because
442         *  the driver cannot determine if the memory type is the certain
443         *  type of SGRAM for which block_write can be used.
444         */
445        psav->GlobalBD.bd1.HighPart.ResBWTile = TILE_FORMAT_LINEAR;/* linear */
446    }
447    else if (pScrn->bitsPerPixel == 16) {
448	psav->GlobalBD.bd1.HighPart.ResBWTile = tile16; /* 16 bpp/destination tiling format */
449
450        ulTmp = (((pScrn->virtualX + 0x3F) & 0x0000FFC0) >> 6) << 20;
451        OUTREG32(TILED_SURFACE_REGISTER_0,ulTmp | TILED_SURF_BPP16);
452    }
453    else if (pScrn->bitsPerPixel == 32) {
454        psav->GlobalBD.bd1.HighPart.ResBWTile = tile32; /* 32 bpp/destination tiling format */
455
456        ulTmp = ( ((pScrn->virtualX + 0x1F) & 0x0000FFE0) >> 5) << 20;
457        OUTREG32(TILED_SURFACE_REGISTER_0,ulTmp | TILED_SURF_BPP32);
458    }
459
460    psav->GlobalBD.bd1.HighPart.ResBWTile |= 0x10;/* disable block write - was 0 */
461    /* HW uses width */
462    psav->GlobalBD.bd1.HighPart.Stride = (unsigned short) psav->lDelta / (pScrn->bitsPerPixel >> 3);
463    psav->GlobalBD.bd1.HighPart.Bpp = (unsigned char) (pScrn->bitsPerPixel);
464    psav->GlobalBD.bd1.Offset = pScrn->fbOffset;
465
466
467    /*
468     * CR88, bit 4 - Block write enabled/disabled.
469     *
470     *      Note: Block write must be disabled when writing to tiled
471     *            memory.  Even when writing to non-tiled memory, block
472     *            write should only be enabled for certain types of SGRAM.
473     */
474    OUTREG8(CRT_ADDRESS_REG,0x88);
475    byte = INREG8(CRT_DATA_REG) | DISABLE_BLOCK_WRITE_2D;
476    OUTREG8(CRT_DATA_REG,byte);
477
478    /*
479     * CR31, bit 0 = 0, Disable address offset bits(CR6A_6-0).
480     *       bit 0 = 1, Enable 8 Mbytes of display memory thru 64K window
481     *                  at A000:0.
482     */
483    OUTREG8(CRT_ADDRESS_REG,MEMORY_CONFIG_REG); /* cr31 */
484    byte = INREG8(CRT_DATA_REG) & (~(ENABLE_CPUA_BASE_A0000));
485    OUTREG8(CRT_DATA_REG,byte); /* perhaps this should be 0x0c */
486
487    /* turn on screen */
488    OUTREG8(SEQ_ADDRESS_REG,0x01);
489    byte = INREG8(SEQ_DATA_REG) & ~0x20;
490    OUTREG8(SEQ_DATA_REG,byte);
491
492    /* program the GBD and SBD's */
493    OUTREG32(S3_GLB_BD_LOW,psav->GlobalBD.bd2.LoPart);
494    OUTREG32(S3_GLB_BD_HIGH,psav->GlobalBD.bd2.HiPart | bci_enable | S3_LITTLE_ENDIAN | S3_BD64);
495    OUTREG32(S3_PRI_BD_LOW,psav->GlobalBD.bd2.LoPart);
496    OUTREG32(S3_PRI_BD_HIGH,psav->GlobalBD.bd2.HiPart);
497    OUTREG32(S3_SEC_BD_LOW,psav->GlobalBD.bd2.LoPart);
498    OUTREG32(S3_SEC_BD_HIGH,psav->GlobalBD.bd2.HiPart);
499}
500
501void SavageSetGBD_3D(ScrnInfoPtr pScrn)
502{
503    SavagePtr psav = SAVPTR(pScrn);
504    unsigned long       ulTmp;
505    unsigned char byte;
506    int bci_enable, tile16, tile32;
507
508    bci_enable = BCI_ENABLE;
509    tile16 = TILE_FORMAT_16BPP;
510    tile32 = TILE_FORMAT_32BPP;
511
512    /* MM81C0 and 81C4 are used to control primary stream. */
513    OUTREG32(PSTREAM_FBADDR0_REG,0x00000000);
514    OUTREG32(PSTREAM_FBADDR1_REG,0x00000000);
515
516    /*
517     *  Program Primary Stream Stride Register.
518     *
519     *  Tell engine if tiling on or off, set primary stream stride, and
520     *  if tiling, set tiling bits/pixel and primary stream tile offset.
521     *  Note that tile offset (bits 16 - 29) must be scanline width in
522     *  bytes/128bytespertile * 256 Qwords/tile.  This is equivalent to
523     *  lDelta * 2.  Remember that if tiling, lDelta is screenwidth in
524     *  bytes padded up to an even number of tilewidths.
525     */
526    if (!psav->bTiled) {
527        OUTREG32(PSTREAM_STRIDE_REG,
528                 (((psav->lDelta * 2) << 16) & 0x3FFFE000) |
529                 (psav->lDelta & 0x00001fff));
530    }
531    else if (pScrn->bitsPerPixel == 16) {
532        /* Scanline-length-in-bytes/128-bytes-per-tile * 256 Qwords/tile */
533        OUTREG32(PSTREAM_STRIDE_REG,
534                 (((psav->lDelta * 2) << 16) & 0x3FFFE000)
535                 | 0x80000000 | (psav->lDelta & 0x00001fff));
536    }
537    else if (pScrn->bitsPerPixel == 32) {
538        OUTREG32(PSTREAM_STRIDE_REG,
539                 (((psav->lDelta * 2) << 16) & 0x3FFFE000)
540                 | 0xC0000000 | (psav->lDelta & 0x00001fff));
541    }
542
543    /*
544     *  CR69, bit 7 = 1
545     *  to use MM streams processor registers to control primary stream.
546     */
547    OUTREG8(CRT_ADDRESS_REG,0x69);
548    byte = INREG8(CRT_DATA_REG) | 0x80;
549    OUTREG8(CRT_DATA_REG,byte);
550
551    OUTREG32(0x8128, 0xFFFFFFFFL);
552    OUTREG32(0x812C, 0xFFFFFFFFL);
553
554    OUTREG32(S3_BCI_GLB_BD_HIGH, bci_enable | S3_LITTLE_ENDIAN | S3_BD64);
555
556
557    /* CR50, bit 7,6,0 = 111, Use GBD.*/
558    OUTREG8(CRT_ADDRESS_REG,0x50);
559    byte = INREG8(CRT_DATA_REG) | 0xC1;
560    OUTREG8(CRT_DATA_REG, byte);
561
562    /*
563     * if MS1NB style linear tiling mode.
564     * bit MM850C[15] = 0 select NB linear tile mode.
565     * bit MM850C[15] = 1 select MS-1 128-bit non-linear tile mode.
566     */
567    ulTmp = INREG32(ADVANCED_FUNC_CTRL) | 0x8000; /* use MS-s style tile mode*/
568    OUTREG32(ADVANCED_FUNC_CTRL,ulTmp);
569
570    /*
571     * Tiled Surface 0 Registers MM48C40:
572     *  bit 0~23: tile surface 0 frame buffer offset
573     *  bit 24~29:tile surface 0 width
574     *  bit 30~31:tile surface 0 bits/pixel
575     *            00: reserved
576     *            01, 8 bits
577     *            10, 16 Bits.
578     *            11, 32 Bits.
579     */
580    /*
581     * Global Bitmap Descriptor Register MM816C
582     *   bit 24~25: tile format
583     *          00: linear
584     *          01: reserved
585     *          10: 16 bpp tiles
586     *          11: 32 bpp tiles
587     *   bit 28: block write disable/enable
588     *          0: enable
589     *          1: disable
590     */
591    if (!psav->bTiled) {
592        /*
593         *  Do not enable block_write even for non-tiling modes, because
594         *  the driver cannot determine if the memory type is the certain
595         *  type of SGRAM for which block_write can be used.
596         */
597        psav->GlobalBD.bd1.HighPart.ResBWTile = TILE_FORMAT_LINEAR;/* linear */
598    }
599    else if (pScrn->bitsPerPixel == 16) {
600	psav->GlobalBD.bd1.HighPart.ResBWTile = tile16; /* 16 bpp/destination tiling format */
601
602        ulTmp = (((pScrn->virtualX + 0x3F) & 0x0000FFC0) >> 6) << 24;
603        OUTREG32(TILED_SURFACE_REGISTER_0,ulTmp | TILED_SURF_BPP16);
604    }
605    else if (pScrn->bitsPerPixel == 32) {
606        psav->GlobalBD.bd1.HighPart.ResBWTile = tile32; /* 32 bpp/destination tiling format */
607
608        ulTmp = ( ((pScrn->virtualX + 0x1F) & 0x0000FFE0) >> 5) << 24;
609        OUTREG32(TILED_SURFACE_REGISTER_0,ulTmp | TILED_SURF_BPP32);
610    }
611
612    psav->GlobalBD.bd1.HighPart.ResBWTile |= 0x10;/* disable block write - was 0 */
613    /* HW uses width */
614    psav->GlobalBD.bd1.HighPart.Stride = (unsigned short) psav->lDelta / (pScrn->bitsPerPixel >> 3);
615    psav->GlobalBD.bd1.HighPart.Bpp = (unsigned char) (pScrn->bitsPerPixel);
616    psav->GlobalBD.bd1.Offset = pScrn->fbOffset;
617
618
619    /*
620     * CR88, bit 4 - Block write enabled/disabled.
621     *
622     *      Note: Block write must be disabled when writing to tiled
623     *            memory.  Even when writing to non-tiled memory, block
624     *            write should only be enabled for certain types of SGRAM.
625     */
626    OUTREG8(CRT_ADDRESS_REG,0x88);
627    byte = INREG8(CRT_DATA_REG) | DISABLE_BLOCK_WRITE_2D;
628    OUTREG8(CRT_DATA_REG,byte);
629
630    /*
631     * CR31, bit 0 = 0, Disable address offset bits(CR6A_6-0).
632     *       bit 0 = 1, Enable 8 Mbytes of display memory thru 64K window
633     *                  at A000:0.
634     */
635    OUTREG8(CRT_ADDRESS_REG,MEMORY_CONFIG_REG); /* cr31 */
636    byte = INREG8(CRT_DATA_REG) & (~(ENABLE_CPUA_BASE_A0000));
637    OUTREG8(CRT_DATA_REG,byte); /* perhaps this should be 0x0c */
638
639    /* turn on screen */
640    OUTREG8(SEQ_ADDRESS_REG,0x01);
641    byte = INREG8(SEQ_DATA_REG) & ~0x20;
642    OUTREG8(SEQ_DATA_REG,byte);
643
644    /* program the GBD and SBD's */
645    OUTREG32(S3_GLB_BD_LOW,psav->GlobalBD.bd2.LoPart);
646    OUTREG32(S3_GLB_BD_HIGH,psav->GlobalBD.bd2.HiPart | bci_enable | S3_LITTLE_ENDIAN | S3_BD64);
647    OUTREG32(S3_PRI_BD_LOW,psav->GlobalBD.bd2.LoPart);
648    OUTREG32(S3_PRI_BD_HIGH,psav->GlobalBD.bd2.HiPart);
649    OUTREG32(S3_SEC_BD_LOW,psav->GlobalBD.bd2.LoPart);
650    OUTREG32(S3_SEC_BD_HIGH,psav->GlobalBD.bd2.HiPart);
651}
652
653void SavageSetGBD_M7(ScrnInfoPtr pScrn)
654{
655    SavagePtr psav = SAVPTR(pScrn);
656    unsigned long ulTmp;
657    unsigned char byte;
658    int bci_enable, tile16, tile32;
659
660    bci_enable = BCI_ENABLE;
661    tile16 = TILE_FORMAT_16BPP;
662    tile32 = TILE_FORMAT_32BPP;
663
664
665    /* following is the enable case */
666
667    /* SR01:turn off screen */
668    OUTREG8 (SEQ_ADDRESS_REG,0x01);
669    byte = INREG8(SEQ_DATA_REG) | 0x20;
670    OUTREG8(SEQ_DATA_REG,byte);
671
672    /*
673     * CR67_3:
674     *  = 1  stream processor MMIO address and stride register
675     *       are used to control the primary stream
676     *  = 0  standard VGA address and stride registers
677     *       are used to control the primary streams
678     */
679    if (psav->IsPrimary) {
680    	OUTREG8(CRT_ADDRESS_REG,0x67);
681    	byte =  INREG8(CRT_DATA_REG) | 0x08;
682    	OUTREG8(CRT_DATA_REG,byte);
683    } else if (psav->IsSecondary) {
684    	/* IGA 2 */
685    	OUTREG16(SEQ_ADDRESS_REG,SELECT_IGA2_READS_WRITES);
686
687    	OUTREG8(CRT_ADDRESS_REG,0x67);
688    	byte =  INREG8(CRT_DATA_REG) | 0x08;
689    	OUTREG8(CRT_DATA_REG,byte);
690
691    	OUTREG16(SEQ_ADDRESS_REG,SELECT_IGA1);
692    } else {
693    	OUTREG8(CRT_ADDRESS_REG,0x67);
694    	byte =  INREG8(CRT_DATA_REG) | 0x08;
695    	OUTREG8(CRT_DATA_REG,byte);
696    	/* IGA 2 */
697    	OUTREG16(SEQ_ADDRESS_REG,SELECT_IGA2_READS_WRITES);
698    	OUTREG8(CRT_ADDRESS_REG,0x67);
699    	byte =  INREG8(CRT_DATA_REG) | 0x08;
700    	OUTREG8(CRT_DATA_REG,byte);
701    	OUTREG16(SEQ_ADDRESS_REG,SELECT_IGA1);
702    }
703    /* Set primary stream to bank 0 */
704    OUTREG8(CRT_ADDRESS_REG, MEMORY_CTRL0_REG);/* CRCA */
705    byte =  INREG8(CRT_DATA_REG) & ~(MEM_PS1 + MEM_PS2) ;
706    OUTREG8(CRT_DATA_REG,byte);
707#if 0
708    /*
709     * if we have 8MB of frame buffer here then we must really be a 16MB
710     * card and that means that the second device is always in the upper
711     * bank of memory (MHS)
712     */
713    if (psav->videoRambytes >= 0x800000) {
714        /* 16MB Video Memory cursor is at the end in Bank 1 */
715        byte |= 0x3;
716        OUTREG16(CRT_ADDRESS_REG, (byte << 8) | MEMORY_CTRL0_REG);
717    }
718#endif
719
720    /* MM81C0 and 81C4 are used to control primary stream. */
721    if (psav->IsPrimary) {
722    	OUTREG32(PRI_STREAM_FBUF_ADDR0,pScrn->fbOffset & 0x7fffff);
723    	OUTREG32(PRI_STREAM_FBUF_ADDR1,pScrn->fbOffset & 0x7fffff);
724    } else if (psav->IsSecondary) {
725    	OUTREG32(PRI_STREAM2_FBUF_ADDR0,pScrn->fbOffset & 0x7fffff);
726    	OUTREG32(PRI_STREAM2_FBUF_ADDR1,pScrn->fbOffset & 0x7fffff);
727    } else {
728    	OUTREG32(PRI_STREAM_FBUF_ADDR0,pScrn->fbOffset & 0x7fffff);
729    	OUTREG32(PRI_STREAM_FBUF_ADDR1,pScrn->fbOffset & 0x7fffff);
730    	OUTREG32(PRI_STREAM2_FBUF_ADDR0,pScrn->fbOffset & 0x7fffff);
731    	OUTREG32(PRI_STREAM2_FBUF_ADDR1,pScrn->fbOffset & 0x7fffff);
732    }
733
734    /*
735     *  Program Primary Stream Stride Register.
736     *
737     *  Tell engine if tiling on or off, set primary stream stride, and
738     *  if tiling, set tiling bits/pixel and primary stream tile offset.
739     *  Note that tile offset (bits 16 - 29) must be scanline width in
740     *  bytes/128bytespertile * 256 Qwords/tile.  This is equivalent to
741     *  lDelta * 2.  Remember that if tiling, lDelta is screenwidth in
742     *  bytes padded up to an even number of tilewidths.
743     */
744    if (!psav->bTiled) {
745 	if (psav->IsPrimary) {
746            OUTREG32(PRI_STREAM_STRIDE,
747                 (((psav->lDelta * 2) << 16) & 0x3FFF0000) |
748                 (psav->lDelta & 0x00003fff));
749	} else if (psav->IsSecondary) {
750            OUTREG32(PRI_STREAM2_STRIDE,
751                 (((psav->lDelta * 2) << 16) & 0x3FFF0000) |
752                 (psav->lDelta & 0x00003fff));
753	} else {
754            OUTREG32(PRI_STREAM_STRIDE,
755                 (((psav->lDelta * 2) << 16) & 0x3FFF0000) |
756                 (psav->lDelta & 0x00003fff));
757            OUTREG32(PRI_STREAM2_STRIDE,
758                 (((psav->lDelta * 2) << 16) & 0x3FFF0000) |
759                 (psav->lDelta & 0x00003fff));
760	}
761
762    } else if (pScrn->bitsPerPixel == 16) {
763        /* Scanline-length-in-bytes/128-bytes-per-tile * 256 Qwords/tile */
764	if (psav->IsPrimary) {
765            OUTREG32(PRI_STREAM_STRIDE,
766                 (((psav->lDelta * 2) << 16) & 0x3FFF0000)
767                 | 0x80000000 | (psav->lDelta & 0x00003fff));
768        } else if (psav->IsSecondary) {
769            OUTREG32(PRI_STREAM2_STRIDE,
770                 (((psav->lDelta * 2) << 16) & 0x3FFF0000)
771                 | 0x80000000 | (psav->lDelta & 0x00003fff));
772        } else {
773            OUTREG32(PRI_STREAM_STRIDE,
774                 (((psav->lDelta * 2) << 16) & 0x3FFF0000)
775                 | 0x80000000 | (psav->lDelta & 0x00003fff));
776            OUTREG32(PRI_STREAM2_STRIDE,
777                 (((psav->lDelta * 2) << 16) & 0x3FFF0000)
778                 | 0x80000000 | (psav->lDelta & 0x00003fff));
779	}
780
781    } else if (pScrn->bitsPerPixel == 32) {
782	if (psav->IsPrimary) {
783            OUTREG32(PRI_STREAM_STRIDE,
784                 (((psav->lDelta * 2) << 16) & 0x3FFF0000)
785                 | 0xC0000000 | (psav->lDelta & 0x00003fff));
786	} else if (psav->IsSecondary) {
787            OUTREG32(PRI_STREAM2_STRIDE,
788                 (((psav->lDelta * 2) << 16) & 0x3FFF0000)
789                 | 0xC0000000 | (psav->lDelta & 0x00003fff));
790	} else {
791            OUTREG32(PRI_STREAM_STRIDE,
792                 (((psav->lDelta * 2) << 16) & 0x3FFF0000)
793                 | 0xC0000000 | (psav->lDelta & 0x00003fff));
794            OUTREG32(PRI_STREAM2_STRIDE,
795                 (((psav->lDelta * 2) << 16) & 0x3FFF0000)
796                 | 0xC0000000 | (psav->lDelta & 0x00003fff));
797	}
798    }
799
800    OUTREG32(0x8128, 0xFFFFFFFFL);
801    OUTREG32(0x812C, 0xFFFFFFFFL);
802
803    if (!psav->IsSecondary)
804    	OUTREG32(S3_BCI_GLB_BD_HIGH, bci_enable | S3_LITTLE_ENDIAN | S3_BD64);
805
806    /* CR50, bit 7,6,0 = 111, Use GBD.*/
807    OUTREG8(CRT_ADDRESS_REG,0x50);
808    byte = INREG8(CRT_DATA_REG) | 0xC1;
809    OUTREG8(CRT_DATA_REG, byte);
810
811    /*
812     * CR78, bit 3  - Block write enabled(1)/disabled(0).
813     *       bit 2  - Block write cycle time(0:2 cycles,1: 1 cycle)
814     *      Note: Block write must be disabled when writing to tiled
815     *            memory.  Even when writing to non-tiled memory, block
816     *            write should only be enabled for certain types of SGRAM.
817     */
818    OUTREG8(CRT_ADDRESS_REG,0x78);
819    /*byte = INREG8(CRT_DATA_REG) & ~0x0C;*/
820    byte = INREG8(CRT_DATA_REG) | 0xfb;
821    OUTREG8(CRT_DATA_REG,byte);
822
823    /*
824     * Tiled Surface 0 Registers MM48C40:
825     *  bit 0~23: tile surface 0 frame buffer offset
826     *  bit 24~29:tile surface 0 width
827     *  bit 30~31:tile surface 0 bits/pixel
828     *            00: reserved
829     *            01, 8 bits
830     *            10, 16 Bits.
831     *            11, 32 Bits.
832     */
833    /*
834     * Global Bitmap Descriptor Register MM816C
835     *   bit 24~25: tile format
836     *          00: linear
837     *          01: reserved
838     *          10: 16 bit
839     *          11: 32 bit
840     *   bit 28: block write disble/enable
841     *          0: enable
842     *          1: disable
843     */
844    if (!psav->bTiled) {
845        /*
846         *  Do not enable block_write even for non-tiling modes, because
847         *  the driver cannot determine if the memory type is the certain
848         *  type of SGRAM for which block_write can be used.
849         */
850        psav->GlobalBD.bd1.HighPart.ResBWTile = TILE_FORMAT_LINEAR;/* linear */
851
852    }
853    else if (pScrn->bitsPerPixel == 16) {
854        psav->GlobalBD.bd1.HighPart.ResBWTile = tile16;/* 16 bit */
855
856	ulTmp =  ((psav->lDelta / 2) >> 6) << 24;
857	if (psav->IsSecondary)
858            OUTREG32(TILED_SURFACE_REGISTER_1,ulTmp | TILED_SURF_BPP16 | pScrn->fbOffset);
859	else
860            OUTREG32(TILED_SURFACE_REGISTER_0,ulTmp | TILED_SURF_BPP16 | pScrn->fbOffset);
861    }
862    else if (pScrn->bitsPerPixel == 32) {
863        psav->GlobalBD.bd1.HighPart.ResBWTile = tile32;/* 32 bit */
864
865	ulTmp =  ((psav->lDelta / 4) >> 5) << 24;
866	if (psav->IsSecondary)
867            OUTREG32(TILED_SURFACE_REGISTER_1,ulTmp | TILED_SURF_BPP32 | pScrn->fbOffset);
868	else
869            OUTREG32(TILED_SURFACE_REGISTER_0,ulTmp | TILED_SURF_BPP32 | pScrn->fbOffset);
870    }
871
872    psav->GlobalBD.bd1.HighPart.ResBWTile |= 0x10;/* disable block write */
873    /* HW uses width */
874    psav->GlobalBD.bd1.HighPart.Stride = (unsigned short)(psav->lDelta / (pScrn->bitsPerPixel >> 3));
875    psav->GlobalBD.bd1.HighPart.Bpp = (unsigned char) (pScrn->bitsPerPixel);
876    psav->GlobalBD.bd1.Offset = pScrn->fbOffset;
877
878
879    /*
880     * CR31, bit 0 = 0, Disable address offset bits(CR6A_6-0).
881     *       bit 0 = 1, Enable 8 Mbytes of display memory thru 64K window
882     *                  at A000:0.
883     */
884#if 0
885    OUTREG8(CRT_ADDRESS_REG,MEMORY_CONFIG_REG); /* cr31 */
886    byte = INREG8(CRT_DATA_REG) & (~(ENABLE_CPUA_BASE_A0000));
887    OUTREG8(CRT_DATA_REG,byte);
888#endif
889    OUTREG8(CRT_ADDRESS_REG,MEMORY_CONFIG_REG); /* cr31 */
890    byte = (INREG8(CRT_DATA_REG) | 0x04) & 0xFE;
891    OUTREG8(CRT_DATA_REG,byte);
892
893    if (!psav->IsSecondary) {
894    	/* program the GBD and SBD's */
895    	OUTREG32(S3_GLB_BD_LOW,psav->GlobalBD.bd2.LoPart );
896    	/* 8: bci enable */
897    	OUTREG32(S3_GLB_BD_HIGH,(psav->GlobalBD.bd2.HiPart
898                             | bci_enable | S3_LITTLE_ENDIAN | S3_BD64));
899    	OUTREG32(S3_PRI_BD_LOW,psav->GlobalBD.bd2.LoPart);
900    	OUTREG32(S3_PRI_BD_HIGH,psav->GlobalBD.bd2.HiPart);
901    	OUTREG32(S3_SEC_BD_LOW,psav->GlobalBD.bd2.LoPart);
902    	OUTREG32(S3_SEC_BD_HIGH,psav->GlobalBD.bd2.HiPart);
903    }
904
905    /* turn on screen */
906    OUTREG8(SEQ_ADDRESS_REG,0x01);
907    byte = INREG8(SEQ_DATA_REG) & ~0X20;
908    OUTREG8(SEQ_DATA_REG,byte);
909}
910
911void SavageSetGBD_PM(ScrnInfoPtr pScrn)
912{
913    SavagePtr psav = SAVPTR(pScrn);
914    unsigned long ulTmp;
915    unsigned char byte;
916    int bci_enable, tile16, tile32;
917
918
919    bci_enable = BCI_ENABLE_TWISTER;
920    tile16 = TILE_DESTINATION;
921    tile32 = TILE_DESTINATION;
922
923
924    /* following is the enable case */
925
926    /* SR01:turn off screen */
927    OUTREG8 (SEQ_ADDRESS_REG,0x01);
928    byte = INREG8(SEQ_DATA_REG) | 0x20;
929    OUTREG8(SEQ_DATA_REG,byte);
930
931    /*
932     * CR67_3:
933     *  = 1  stream processor MMIO address and stride register
934     *       are used to control the primary stream
935     *  = 0  standard VGA address and stride registers
936     *       are used to control the primary streams
937     */
938    if (psav->IsPrimary) {
939    	OUTREG8(CRT_ADDRESS_REG,0x67);
940    	byte =  INREG8(CRT_DATA_REG) | 0x08;
941    	OUTREG8(CRT_DATA_REG,byte);
942    } else if (psav->IsSecondary) {
943    	/* IGA 2 */
944    	OUTREG16(SEQ_ADDRESS_REG,SELECT_IGA2_READS_WRITES);
945
946    	OUTREG8(CRT_ADDRESS_REG,0x67);
947    	byte =  INREG8(CRT_DATA_REG) | 0x08;
948    	OUTREG8(CRT_DATA_REG,byte);
949
950    	OUTREG16(SEQ_ADDRESS_REG,SELECT_IGA1);
951    } else {
952    	OUTREG8(CRT_ADDRESS_REG,0x67);
953    	byte =  INREG8(CRT_DATA_REG) | 0x08;
954    	OUTREG8(CRT_DATA_REG,byte);
955    	/* IGA 2 */
956    	OUTREG16(SEQ_ADDRESS_REG,SELECT_IGA2_READS_WRITES);
957
958    	OUTREG8(CRT_ADDRESS_REG,0x67);
959    	byte =  INREG8(CRT_DATA_REG) | 0x08;
960    	OUTREG8(CRT_DATA_REG,byte);
961
962    	OUTREG16(SEQ_ADDRESS_REG,SELECT_IGA1);
963    }
964
965    /*
966     * load ps1 active registers as determined by MM81C0/81C4
967     * load ps2 active registers as determined by MM81B0/81B4
968     */
969    OUTREG8(CRT_ADDRESS_REG,0x65);
970    byte =  INREG8(CRT_DATA_REG) | 0x03;
971    OUTREG8(CRT_DATA_REG,byte);
972
973    /*
974     *  Program Primary Stream Stride Register.
975     *
976     *  Tell engine if tiling on or off, set primary stream stride, and
977     *  if tiling, set tiling bits/pixel and primary stream tile offset.
978     *  Note that tile offset (bits 16 - 29) must be scanline width in
979     *  bytes/128bytespertile * 256 Qwords/tile.  This is equivalent to
980     *  lDelta * 2.  Remember that if tiling, lDelta is screenwidth in
981     *  bytes padded up to an even number of tilewidths.
982     */
983    if (!psav->bTiled) {
984	if (psav->IsPrimary) {
985            OUTREG32(PRI_STREAM_STRIDE,
986                 (((psav->lDelta * 2) << 16) & 0x3FFF0000) |
987                 (psav->lDelta & 0x00001fff));
988	} else if (psav->IsSecondary) {
989            OUTREG32(PRI_STREAM2_STRIDE,
990                 (((psav->lDelta * 2) << 16) & 0x3FFF0000) |
991                 (psav->lDelta & 0x00001fff));
992	} else {
993            OUTREG32(PRI_STREAM_STRIDE,
994                 (((psav->lDelta * 2) << 16) & 0x3FFF0000) |
995                 (psav->lDelta & 0x00001fff));
996            OUTREG32(PRI_STREAM2_STRIDE,
997                 (((psav->lDelta * 2) << 16) & 0x3FFF0000) |
998                 (psav->lDelta & 0x00001fff));
999	}
1000    } else if (pScrn->bitsPerPixel == 16) {
1001        /* Scanline-length-in-bytes/128-bytes-per-tile * 256 Qwords/tile */
1002	if (psav->IsPrimary) {
1003            OUTREG32(PRI_STREAM_STRIDE,
1004                 (((psav->lDelta * 2) << 16) & 0x3FFF0000)
1005                 | 0x80000000 | (psav->lDelta & 0x00001fff));
1006	} else if (psav->IsSecondary) {
1007            OUTREG32(PRI_STREAM2_STRIDE,
1008                 (((psav->lDelta * 2) << 16) & 0x3FFF0000)
1009                 | 0x80000000 | (psav->lDelta & 0x00001fff));
1010	} else {
1011            OUTREG32(PRI_STREAM_STRIDE,
1012                 (((psav->lDelta * 2) << 16) & 0x3FFF0000)
1013                 | 0x80000000 | (psav->lDelta & 0x00001fff));
1014            OUTREG32(PRI_STREAM2_STRIDE,
1015                 (((psav->lDelta * 2) << 16) & 0x3FFF0000)
1016                 | 0x80000000 | (psav->lDelta & 0x00001fff));
1017	}
1018
1019    } else if (pScrn->bitsPerPixel == 32) {
1020	if (psav->IsPrimary) {
1021            OUTREG32(PRI_STREAM_STRIDE,
1022                 (((psav->lDelta * 2) << 16) & 0x3FFF0000)
1023                 | 0xC0000000 | (psav->lDelta & 0x00001fff));
1024	} else if (psav->IsSecondary) {
1025            OUTREG32(PRI_STREAM2_STRIDE,
1026                 (((psav->lDelta * 2) << 16) & 0x3FFF0000)
1027                 | 0xC0000000 | (psav->lDelta & 0x00001fff));
1028	} else {
1029            OUTREG32(PRI_STREAM_STRIDE,
1030                 (((psav->lDelta * 2) << 16) & 0x3FFF0000)
1031                 | 0xC0000000 | (psav->lDelta & 0x00001fff));
1032            OUTREG32(PRI_STREAM2_STRIDE,
1033                 (((psav->lDelta * 2) << 16) & 0x3FFF0000)
1034                 | 0xC0000000 | (psav->lDelta & 0x00001fff));
1035	}
1036    }
1037
1038    /* MM81C0 and 81C4 are used to control primary stream. */
1039    if (psav->IsPrimary) {
1040        OUTREG32(PRI_STREAM_FBUF_ADDR0,pScrn->fbOffset);
1041        OUTREG32(PRI_STREAM_FBUF_ADDR1,0x80000000);
1042    } else if (psav->IsSecondary) {
1043        OUTREG32(PRI_STREAM2_FBUF_ADDR0,(pScrn->fbOffset & 0xfffffffc) | 0x80000000);
1044        OUTREG32(PRI_STREAM2_FBUF_ADDR1,pScrn->fbOffset & 0xffffffc);
1045    } else {
1046        OUTREG32(PRI_STREAM_FBUF_ADDR0,pScrn->fbOffset);
1047        OUTREG32(PRI_STREAM_FBUF_ADDR1,0x80000000);
1048        OUTREG32(PRI_STREAM2_FBUF_ADDR0,(pScrn->fbOffset & 0xfffffffc) | 0x80000000);
1049        OUTREG32(PRI_STREAM2_FBUF_ADDR1,pScrn->fbOffset & 0xffffffc);
1050    }
1051
1052    OUTREG32(0x8128, 0xFFFFFFFFL);
1053    OUTREG32(0x812C, 0xFFFFFFFFL);
1054
1055    if (!psav->IsSecondary)
1056    	/* bit 28:block write disable */
1057    	OUTREG32(S3_GLB_BD_HIGH, bci_enable | S3_BD64 | 0x10000000);
1058
1059    /* CR50, bit 7,6,0 = 111, Use GBD.*/
1060    OUTREG8(CRT_ADDRESS_REG,0x50);
1061    byte = INREG8(CRT_DATA_REG) | 0xC1;
1062    OUTREG8(CRT_DATA_REG, byte);
1063
1064    if (!psav->bTiled) {
1065        /*
1066         *  Do not enable block_write even for non-tiling modes, because
1067         *  the driver cannot determine if the memory type is the certain
1068         *  type of SGRAM for which block_write can be used.
1069         */
1070        psav->GlobalBD.bd1.HighPart.ResBWTile = TILE_FORMAT_LINEAR;/* linear */
1071
1072    }
1073    else if (pScrn->bitsPerPixel == 16) {
1074        psav->GlobalBD.bd1.HighPart.ResBWTile = tile16;/* tile format destination */
1075
1076        ulTmp =  (((pScrn->virtualX + 0x3f) & 0x0000ffc0) >> 6) << 20;
1077	if (psav->IsSecondary)
1078            OUTREG32(TILED_SURFACE_REGISTER_1,ulTmp | TILED_SURF_BPP16 | (pScrn->fbOffset>>6));
1079	else
1080            OUTREG32(TILED_SURFACE_REGISTER_0,ulTmp | TILED_SURF_BPP16 | (pScrn->fbOffset>>6));
1081    }
1082    else if (pScrn->bitsPerPixel == 32) {
1083        psav->GlobalBD.bd1.HighPart.ResBWTile = tile32;/* tile format destination */
1084
1085        ulTmp =  (((pScrn->virtualX + 0x1f) & 0x0000ffe0) >> 5) << 20;
1086	if (psav->IsSecondary)
1087            OUTREG32(TILED_SURFACE_REGISTER_1,ulTmp | TILED_SURF_BPP32 | (pScrn->fbOffset>>6));
1088	else
1089            OUTREG32(TILED_SURFACE_REGISTER_0,ulTmp | TILED_SURF_BPP32 | (pScrn->fbOffset>>6));
1090    }
1091
1092    psav->GlobalBD.bd1.HighPart.ResBWTile |= 0x10;/* disable block write */
1093    /* HW uses width */
1094    psav->GlobalBD.bd1.HighPart.Stride = (unsigned short)(psav->lDelta / (pScrn->bitsPerPixel >> 3));
1095    psav->GlobalBD.bd1.HighPart.Bpp = (unsigned char) (pScrn->bitsPerPixel);
1096    psav->GlobalBD.bd1.Offset = pScrn->fbOffset;
1097
1098    /*
1099     * CR31, bit 0 = 0, Disable address offset bits(CR6A_6-0).
1100     *       bit 0 = 1, Enable 8 Mbytes of display memory thru 64K window
1101     *                  at A000:0.
1102     */
1103    OUTREG8(CRT_ADDRESS_REG,MEMORY_CONFIG_REG);
1104    byte = INREG8(CRT_DATA_REG) & (~(ENABLE_CPUA_BASE_A0000));
1105    OUTREG8(CRT_DATA_REG,byte);
1106
1107    if (!psav->IsSecondary) {
1108    	/* program the GBD and SBDs */
1109    	OUTREG32(S3_GLB_BD_LOW,psav->GlobalBD.bd2.LoPart );
1110    	OUTREG32(S3_GLB_BD_HIGH,(psav->GlobalBD.bd2.HiPart
1111			     | bci_enable | S3_LITTLE_ENDIAN | S3_BD64));
1112    	OUTREG32(S3_PRI_BD_LOW,psav->GlobalBD.bd2.LoPart);
1113    	OUTREG32(S3_PRI_BD_HIGH,psav->GlobalBD.bd2.HiPart);
1114    	OUTREG32(S3_SEC_BD_LOW,psav->GlobalBD.bd2.LoPart);
1115    	OUTREG32(S3_SEC_BD_HIGH,psav->GlobalBD.bd2.HiPart);
1116    }
1117
1118    /* turn on screen */
1119    OUTREG8(SEQ_ADDRESS_REG,0x01);
1120    byte = INREG8(SEQ_DATA_REG) & ~0x20;
1121    OUTREG8(SEQ_DATA_REG,byte);
1122}
1123
1124void SavageSetGBD_2000(ScrnInfoPtr pScrn)
1125{
1126    SavagePtr psav = SAVPTR(pScrn);
1127    unsigned long ulTmp, ulYRange;
1128    unsigned char byte;
1129    int bci_enable, tile16, tile32;
1130
1131    bci_enable = BCI_ENABLE_TWISTER;
1132    tile16 = TILE_DESTINATION;
1133    tile32 = TILE_DESTINATION;
1134
1135    if (pScrn->virtualX > 1024)
1136      ulYRange = 0x40000000;
1137    else
1138      ulYRange = 0x20000000;
1139
1140
1141    /* following is the enable case */
1142
1143    /* SR01:turn off screen */
1144    OUTREG8 (SEQ_ADDRESS_REG,0x01);
1145    byte = INREG8(SEQ_DATA_REG) | 0x20;
1146    OUTREG8(SEQ_DATA_REG,byte);
1147
1148
1149    /* MM81C0 and 81B0 are used to control primary stream. */
1150    OUTREG32(PRI_STREAM_FBUF_ADDR0, pScrn->fbOffset);
1151    OUTREG32(PRI_STREAM2_FBUF_ADDR0, pScrn->fbOffset);
1152
1153
1154    /*
1155     *  Program Primary Stream Stride Register.
1156     *
1157     *  Tell engine if tiling on or off, set primary stream stride, and
1158     *  if tiling, set tiling bits/pixel and primary stream tile offset.
1159     *  Note that tile offset (bits 16 - 29) must be scanline width in
1160     *  bytes/128bytespertile * 256 Qwords/tile.  This is equivalent to
1161     *  lDelta * 2.  Remember that if tiling, lDelta is screenwidth in
1162     *  bytes padded up to an even number of tilewidths.
1163     */
1164    if (!psav->bTiled) {
1165        OUTREG32(PRI_STREAM_STRIDE,
1166		 ((psav->lDelta << 4) & 0x7ff0));
1167        OUTREG32(PRI_STREAM2_STRIDE,
1168                 ((psav->lDelta << 4) & 0x7ff0));
1169    } else {
1170        OUTREG32(PRI_STREAM_STRIDE,
1171		 (0x80000000 |((psav->lDelta << 4) & 0x7ff0)));
1172        OUTREG32(PRI_STREAM2_STRIDE,
1173                 (0x80000000 |((psav->lDelta << 4) & 0x7ff0)));
1174    }
1175
1176    /*
1177     * CR67_3:
1178     *  = 1  stream processor MMIO address and stride register
1179     *       are used to control the primary stream
1180     *  = 0  standard VGA address and stride registers
1181     *       are used to control the primary streams
1182     */
1183
1184    OUTREG8(CRT_ADDRESS_REG,0x67);
1185    byte =  INREG8(CRT_DATA_REG) | 0x08;
1186    OUTREG8(CRT_DATA_REG,byte);
1187
1188
1189    OUTREG32(0x8128, 0xFFFFFFFFL);
1190    OUTREG32(0x812C, 0xFFFFFFFFL);
1191
1192    /* bit 28:block write disable */
1193    OUTREG32(S3_GLB_BD_HIGH, bci_enable | S3_BD64 | 0x10000000);
1194
1195    /* CR50, bit 7,6,0 = 111, Use GBD.*/
1196    OUTREG8(CRT_ADDRESS_REG,0x50);
1197    byte = INREG8(CRT_DATA_REG) | 0xC1;
1198    OUTREG8(CRT_DATA_REG, byte);
1199
1200    /* CR73 bit 5 = 0 block write disable */
1201    OUTREG8(CRT_ADDRESS_REG,0x73);
1202    byte = INREG8(CRT_DATA_REG) & ~0x20;
1203    OUTREG8(CRT_DATA_REG, byte);
1204
1205    if (!psav->bTiled) {
1206        /*
1207         *  Do not enable block_write even for non-tiling modes, because
1208         *  the driver cannot determine if the memory type is the certain
1209         *  type of SGRAM for which block_write can be used.
1210         */
1211        psav->GlobalBD.bd1.HighPart.ResBWTile = TILE_FORMAT_LINEAR;/* linear */
1212
1213    }
1214    else if (pScrn->bitsPerPixel == 16) {
1215        psav->GlobalBD.bd1.HighPart.ResBWTile = tile16;/* tile format destination */
1216        ulTmp =  (((pScrn->virtualX + 0x3f) & 0x0000ffc0) >> 6) << 23;
1217        OUTREG32(TILED_SURFACE_REGISTER_0,ulTmp | TILED_SURF_BPP16_2000 | ulYRange);
1218        ulTmp |= (TILED_SURF_BPP16_2000 | ulYRange);
1219        OUTREG32(PRI_STREAM_STRIDE, ((ulTmp >> 19) & 0x03f0) | 0x80000000);
1220        OUTREG32(PRI_STREAM2_STRIDE, ((ulTmp >> 19) & 0x03f0) | 0x80000000);
1221    }
1222    else if (pScrn->bitsPerPixel == 32) {
1223        psav->GlobalBD.bd1.HighPart.ResBWTile = tile32;/* tile format destination */
1224        ulTmp =  (((pScrn->virtualX + 0x1f) & 0x0000ffe0) >> 5) << 23;
1225        OUTREG32(TILED_SURFACE_REGISTER_0,ulTmp | TILED_SURF_BPP32_2000 | ulYRange);
1226        ulTmp |= (TILED_SURF_BPP32_2000 | ulYRange);
1227        OUTREG32(PRI_STREAM_STRIDE, ((ulTmp >> 19) & 0x03f0) | 0x80000000);
1228        OUTREG32(PRI_STREAM2_STRIDE, ((ulTmp >> 19) & 0x03f0) | 0x80000000);
1229    }
1230
1231    psav->GlobalBD.bd1.HighPart.ResBWTile |= 0x10;/* disable block write */
1232    /* HW uses width */
1233    psav->GlobalBD.bd1.HighPart.Stride = (unsigned short)(psav->lDelta / (pScrn->bitsPerPixel >> 3));
1234    psav->GlobalBD.bd1.HighPart.Bpp = (unsigned char) (pScrn->bitsPerPixel);
1235    psav->GlobalBD.bd1.Offset = pScrn->fbOffset;
1236
1237    /*
1238     * CR31, bit 0 = 0, Disable address offset bits(CR6A_6-0).
1239     *       bit 0 = 1, Enable 8 Mbytes of display memory thru 64K window
1240     *                  at A000:0.
1241     */
1242    OUTREG8(CRT_ADDRESS_REG,MEMORY_CONFIG_REG);
1243    byte = INREG8(CRT_DATA_REG) & (~(ENABLE_CPUA_BASE_A0000));
1244    OUTREG8(CRT_DATA_REG,byte);
1245
1246    /* program the GBD and SBDs */
1247    OUTREG32(S3_GLB_BD_LOW,psav->GlobalBD.bd2.LoPart );
1248    OUTREG32(S3_GLB_BD_HIGH,(psav->GlobalBD.bd2.HiPart
1249			     | bci_enable | S3_LITTLE_ENDIAN | S3_BD64));
1250    OUTREG32(S3_PRI_BD_LOW,psav->GlobalBD.bd2.LoPart);
1251    OUTREG32(S3_PRI_BD_HIGH,psav->GlobalBD.bd2.HiPart);
1252    OUTREG32(S3_SEC_BD_LOW,psav->GlobalBD.bd2.LoPart);
1253    OUTREG32(S3_SEC_BD_HIGH,psav->GlobalBD.bd2.HiPart);
1254
1255    /* turn on screen */
1256    OUTREG8(SEQ_ADDRESS_REG,0x01);
1257    byte = INREG8(SEQ_DATA_REG) & ~0x20;
1258    OUTREG8(SEQ_DATA_REG,byte);
1259}
1260
1261static
1262void SavageRestoreAccelState(ScrnInfoPtr pScrn)
1263{
1264    SavagePtr psav = SAVPTR(pScrn);
1265
1266    psav->WaitIdleEmpty(psav);
1267
1268    return;
1269}
1270
1271/* Acceleration init function, sets up pointers to our accelerated functions */
1272
1273Bool
1274SavageInitAccel(ScreenPtr pScreen)
1275{
1276    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
1277    SavagePtr psav = SAVPTR(pScrn);
1278
1279#ifdef XF86DRI
1280    if (psav->directRenderingEnabled) {
1281        SAVAGEDRIServerPrivatePtr pSAVAGEDRIServer = psav->DRIServerInfo;
1282        BoxRec MemBox;
1283        int cpp = pScrn->bitsPerPixel / 8;
1284        int widthBytes = psav->lDelta;
1285        int bufferSize = ((pScrn->virtualY * widthBytes + SAVAGE_BUFFER_ALIGN)
1286                          & ~SAVAGE_BUFFER_ALIGN);
1287        int tiledWidth, tiledwidthBytes,tiledBufferSize;
1288
1289        pSAVAGEDRIServer->frontbufferSize = bufferSize;
1290        tiledwidthBytes = psav->lDelta;
1291	tiledWidth = tiledwidthBytes / cpp;
1292
1293        if (cpp == 2) {
1294            tiledBufferSize = ((pScrn->virtualX+63)/64)*((pScrn->virtualY+15)/16)
1295                *2048;
1296        } else {
1297            tiledBufferSize = ((pScrn->virtualX+31)/32)*((pScrn->virtualY+15)/16)
1298                *2048;
1299        }
1300        /*set Depth buffer to 32bpp*/
1301        /*tiledwidthBytes_Z = ((pScrn->virtualX + 31)& ~0x0000001F)*4;
1302          tiledBufferSize_Z = ((pScrn->virtualX+31)/32)*((pScrn->virtualY+15)/16)
1303          *2048;*/
1304
1305        pSAVAGEDRIServer->backbufferSize = tiledBufferSize;
1306        /*pSAVAGEDRIServer->depthbufferSize = tiledBufferSize_Z;*/
1307        pSAVAGEDRIServer->depthbufferSize = tiledBufferSize;
1308
1309        xf86DrvMsg(pScrn->scrnIndex,X_INFO,
1310                   "virtualX:%d,virtualY:%d\n",
1311                   pScrn->virtualX,pScrn->virtualY);
1312        xf86DrvMsg( pScrn->scrnIndex, X_INFO,
1313                    "bpp:%d,tiledwidthBytes:%d,tiledBufferSize:%d \n",
1314                    pScrn->bitsPerPixel,
1315                    tiledwidthBytes,tiledBufferSize);
1316
1317        xf86DrvMsg( pScrn->scrnIndex, X_INFO,
1318                    "bpp:%d,widthBytes:%d,BufferSize:%d \n",
1319                    pScrn->bitsPerPixel,
1320                    widthBytes,bufferSize);
1321
1322        pSAVAGEDRIServer->frontOffset = pScrn->fbOffset; /* 0 */
1323        pSAVAGEDRIServer->frontPitch = widthBytes;
1324
1325        /* Try for front, back, depth, and two framebuffers worth of
1326         * pixmap cache.  Should be enough for a fullscreen background
1327         * image plus some leftovers.
1328         */
1329        /*     pSAVAGEDRIServer->textureSize = psav->videoRambytes -
1330               tiledBufferSize -
1331               tiledBufferSize_Z -
1332               -0x602000;*/
1333        pSAVAGEDRIServer->textureSize = psav->videoRambytes -
1334            4096 - /* hw cursor*/
1335            psav->cobSize - /*COB*/
1336            bufferSize-
1337            tiledBufferSize -
1338            tiledBufferSize -
1339            0x200000;
1340
1341        xf86DrvMsg( pScrn->scrnIndex, X_INFO,
1342                    "videoRambytes:0x%08x \n",
1343                    psav->videoRambytes);
1344
1345        xf86DrvMsg( pScrn->scrnIndex, X_INFO,
1346                    "textureSize:0x%08x \n",
1347                    pSAVAGEDRIServer->textureSize);
1348
1349        /* If that gives us less than half the available memory, let's
1350         * be greedy and grab some more.  Sorry, I care more about 3D
1351         * performance than playing nicely, and you'll get around a full
1352         * framebuffer's worth of pixmap cache anyway.
1353         */
1354#if 0
1355        if ( pSAVAGEDRIServer->textureSize < (int)psav->FbMapSize / 2 ) {
1356            pSAVAGEDRIServer->textureSize = psav->FbMapSize - 4 * bufferSize;
1357        }
1358#endif
1359        /* Check to see if there is more room available after the maximum
1360         * scanline for textures.
1361         */
1362#if 0
1363        if ( (int)psav->FbMapSize - maxlines * widthBytes - bufferSize * 2
1364             > pSAVAGEDRIServer->textureSize ) {
1365            pSAVAGEDRIServer->textureSize = (psav->FbMapSize -
1366                                             maxlines * widthBytes -
1367                                             bufferSize * 2);
1368        }
1369#endif
1370        /* Set a minimum usable local texture heap size.  This will fit
1371         * two 256x256x32bpp textures.
1372         */
1373        if ( pSAVAGEDRIServer->textureSize < 512 * 1024 ) {
1374            pSAVAGEDRIServer->textureOffset = 0;
1375            pSAVAGEDRIServer->textureSize = 0;
1376        }
1377
1378        xf86DrvMsg( pScrn->scrnIndex, X_INFO,
1379                    "textureSize:0x%08x \n",
1380                    pSAVAGEDRIServer->textureSize);
1381
1382        /* Reserve space for textures */
1383        /*       if (pSAVAGEDRIServer->textureSize)*/
1384        pSAVAGEDRIServer->textureOffset = (psav->videoRambytes -
1385                                           4096 - /* hw cursor*/
1386                                           psav->cobSize - /*COB*/
1387                                           pSAVAGEDRIServer->textureSize) & ~SAVAGE_BUFFER_ALIGN;
1388
1389        xf86DrvMsg( pScrn->scrnIndex, X_INFO,
1390                    "textureOffset:0x%08x \n",
1391                    pSAVAGEDRIServer->textureOffset);
1392
1393        /* Reserve space for the shared depth buffer */
1394        /*pSAVAGEDRIServer->depthOffset = (pSAVAGEDRIServer->textureOffset -
1395          tiledBufferSize_Z + SAVAGE_BUFFER_ALIGN) &  ~SAVAGE_BUFFER_ALIGN;
1396        */
1397        pSAVAGEDRIServer->depthOffset = (pSAVAGEDRIServer->textureOffset -
1398                                         tiledBufferSize) & ~SAVAGE_BUFFER_ALIGN;
1399        /*pSAVAGEDRIServer->depthPitch = tiledwidthBytes_Z;*/
1400        pSAVAGEDRIServer->depthPitch = tiledwidthBytes;
1401
1402        xf86DrvMsg( pScrn->scrnIndex, X_INFO,
1403                    "depthOffset:0x%08x,depthPitch:%d\n",
1404                    pSAVAGEDRIServer->depthOffset,pSAVAGEDRIServer->depthPitch);
1405
1406        /* Reserve space for the shared back buffer */
1407        pSAVAGEDRIServer->backOffset = (pSAVAGEDRIServer->depthOffset -
1408                                        tiledBufferSize ) & ~SAVAGE_BUFFER_ALIGN;
1409
1410        pSAVAGEDRIServer->backPitch = tiledwidthBytes;
1411
1412        xf86DrvMsg( pScrn->scrnIndex, X_INFO,
1413                    "backOffset:0x%08x,backPitch:%d\n",
1414                    pSAVAGEDRIServer->backOffset,pSAVAGEDRIServer->backPitch);
1415
1416	/* Compute bitmap descriptors for front, back and depth buffers */
1417	if ((psav->Chipset == S3_TWISTER)
1418	    || (psav->Chipset == S3_PROSAVAGE)
1419	    || (psav->Chipset == S3_PROSAVAGEDDR)
1420	    || (psav->Chipset == S3_SUPERSAVAGE)) {
1421	    pSAVAGEDRIServer->frontBitmapDesc =
1422		BCI_BD_BW_DISABLE | /* block write disabled */
1423		(1<<24) | /* destination tile format */
1424		(pScrn->bitsPerPixel<<16) | /* bpp */
1425		tiledWidth; /* stride */
1426	    pSAVAGEDRIServer->backBitmapDesc =
1427		BCI_BD_BW_DISABLE |
1428		(1<<24) |
1429		(pScrn->bitsPerPixel<<16) |
1430		tiledWidth;
1431	    pSAVAGEDRIServer->depthBitmapDesc =
1432		BCI_BD_BW_DISABLE |
1433		(1<<24) |
1434		(pScrn->bitsPerPixel<<16) | /* FIXME: allow zpp != cpp */
1435		tiledWidth;
1436	} else {
1437	    pSAVAGEDRIServer->frontBitmapDesc =
1438		BCI_BD_BW_DISABLE | /* block write disabled */
1439		(cpp==2 ? BCI_BD_TILE_16:BCI_BD_TILE_32) | /*16/32 bpp tile format */
1440		(pScrn->bitsPerPixel<<16) | /* bpp */
1441		tiledWidth; /* stride */
1442	    pSAVAGEDRIServer->backBitmapDesc =
1443		BCI_BD_BW_DISABLE |
1444		(cpp==2 ? BCI_BD_TILE_16:BCI_BD_TILE_32) |
1445		(pScrn->bitsPerPixel<<16) |
1446		tiledWidth;
1447	    pSAVAGEDRIServer->depthBitmapDesc =
1448		BCI_BD_BW_DISABLE |
1449		(cpp==2 ? BCI_BD_TILE_16:BCI_BD_TILE_32) |
1450		(pScrn->bitsPerPixel<<16) | /* FIXME: allow zpp != cpp */
1451		tiledWidth;
1452	}
1453
1454        /*scanlines = pSAVAGEDRIServer->backOffset / widthBytes - 1;*/
1455        /*if ( scanlines > maxlines ) scanlines = maxlines;*/
1456        /* CR47983, XvMC do not work on system with frame buffer less than 32MB.
1457         * VBE reports frame buffer size a little less than 16MB, this makes the condition
1458         *   truns out FALSE.
1459         * Now just reduce the level to 14.5MB, things should be OK, while the hwmc frame buffer layout
1460         *    caculation need more understanding and should be fixed.
1461         */
1462        /*if total memory is less than 16M, there is no HWMC support */
1463        if((psav->videoRambytes < /*16*/(14*1024+512)*1024L) || psav->bDisableXvMC)
1464        {
1465            psav->hwmcOffset = 0;
1466            psav->hwmcSize = 0;
1467        }
1468        else
1469        {
1470            psav->hwmcSize = (10*1024+512)*1024;  /* HWMC needs 10MB FB */
1471            psav->hwmcOffset = (psav->videoRambytes - 0x2000 - psav->hwmcSize) &
1472                ~SAVAGE_BUFFER_ALIGN;
1473            if (psav->hwmcOffset < bufferSize) {
1474                /* If hwmc buffer will lay in on-screen buffer. */
1475                psav->hwmcSize = 0;
1476                psav->hwmcOffset = 0;
1477            }
1478        }
1479
1480        /* CR48438: Title: "Lots of garbage appear on the background when
1481         *  drag the DVD player XINE window at 1024x768 or higher mode."
1482         * hwmc used xserver's memory, now xserver will get less memory.
1483         * Both 3D and hwmc's memory usage are considered now.
1484         */
1485#if 0
1486        if (pSAVAGEDRIServer->backOffset < psav->hwmcOffset )
1487            psav->cyMemory = pSAVAGEDRIServer->backOffset / widthBytes - 1;
1488        else
1489            psav->cyMemory = psav->hwmcOffset / widthBytes -1;
1490#endif
1491
1492        psav->cyMemory = pSAVAGEDRIServer->backOffset / widthBytes - 1;
1493        if (psav->cyMemory > 0x7FFF) {
1494            psav->cyMemory = 0x7FFF;
1495        }
1496
1497	psav->EXAendfb = pSAVAGEDRIServer->backOffset & ~SAVAGE_BUFFER_ALIGN;
1498
1499        xf86DrvMsg( pScrn->scrnIndex, X_INFO,
1500                    "Reserved back buffer at offset 0x%x\n",
1501                    pSAVAGEDRIServer->backOffset );
1502        xf86DrvMsg( pScrn->scrnIndex, X_INFO,
1503                    "Reserved depth buffer at offset 0x%x\n",
1504                    pSAVAGEDRIServer->depthOffset );
1505        xf86DrvMsg( pScrn->scrnIndex, X_INFO,
1506                    "Reserved %d kb for textures at offset 0x%x\n",
1507                    pSAVAGEDRIServer->textureSize/1024,
1508                    pSAVAGEDRIServer->textureOffset );
1509    }
1510    else
1511#endif
1512    {
1513
1514        /*
1515         * why this code? because BoxRec members are  short int
1516         * if cyMemory is bigger than 0x7fff,then it will overflow
1517         */
1518        if (psav->cyMemory > 0x7FFF) {
1519            psav->cyMemory = 0x7FFF;
1520        }
1521
1522	if (psav->IsPrimary) {
1523	    psav->EXAendfb = psav->videoRambytes -
1524            		     4096 - /* hw cursor*/
1525			     0x200000;
1526	} else {
1527	    psav->EXAendfb = psav->videoRambytes -
1528            		     4096 - /* hw cursor*/
1529            		     psav->cobSize - /*COB*/
1530			     0x200000;
1531	}
1532
1533    }
1534
1535    if (psav->useEXA)
1536	return SavageEXAInit(pScreen);
1537    else
1538    	return SavageXAAInit(pScreen);
1539}
1540
1541/* Routines for debugging. */
1542
1543
1544unsigned long
1545writedw( unsigned long addr, unsigned long value )
1546{
1547    SavagePtr psav = SAVPTR(gpScrn);
1548    OUTREG( addr, value );
1549    return INREG( addr );
1550}
1551
1552unsigned long
1553readdw( unsigned long addr )
1554{
1555    SavagePtr psav = SAVPTR(gpScrn);
1556    return INREG( addr );
1557}
1558
1559unsigned long
1560readfb( unsigned long addr )
1561{
1562    SavagePtr psav = SAVPTR(gpScrn);
1563    char * videobuffer = (char *) psav->FBBase;
1564    return *(volatile unsigned long*)(videobuffer + (addr & ~3) );
1565}
1566
1567unsigned long
1568writefb( unsigned long addr, unsigned long value )
1569{
1570    SavagePtr psav = SAVPTR(gpScrn);
1571    char * videobuffer = (char *) psav->FBBase;
1572    *(unsigned long*)(videobuffer + (addr & ~3)) = value;
1573    return *(volatile unsigned long*)(videobuffer + (addr & ~3) );
1574}
1575
1576void
1577writescan( unsigned long scan, unsigned long color )
1578{
1579    SavagePtr psav = SAVPTR(gpScrn);
1580    int i;
1581    char * videobuffer = (char *)psav->FBBase;
1582    videobuffer += scan * gpScrn->displayWidth * gpScrn->bitsPerPixel >> 3;
1583    for( i = gpScrn->displayWidth; --i; ) {
1584	switch( gpScrn->bitsPerPixel ) {
1585	    case 8:
1586		*videobuffer++ = color;
1587		break;
1588	    case 16:
1589		*(CARD16 *)videobuffer = color;
1590		videobuffer += 2;
1591		break;
1592	    case 32:
1593		*(CARD32 *)videobuffer = color;
1594		videobuffer += 4;
1595		break;
1596	}
1597    }
1598}
1599