savage_accel.c revision 2b2b4fcb
1
2/*
3 *
4 * Copyright 1995-1997 The XFree86 Project, Inc.
5 *
6 */
7
8/*
9 * The accel file for the Savage driver.
10 *
11 * Created 20/03/97 by Sebastien Marineau for 3.3.6
12 * Modified 17-Nov-2000 by Tim Roberts for 4.0.1
13 * Modified Feb-2004 by Alex Deucher - integrating DRI support
14 * Revision:
15 *
16 */
17
18#ifdef HAVE_CONFIG_H
19#include "config.h"
20#endif
21
22#include "savage_driver.h"
23#include "savage_regs.h"
24#include "savage_bci.h"
25#include "savage_streams.h"
26
27#ifdef SAVAGEDRI
28#define _XF86DRI_SERVER_
29#include "savage_dri.h"
30#endif
31
32extern int gSavageEntityIndex;
33
34/* Forward declaration of functions used in the driver */
35
36unsigned long writedw( unsigned long addr, unsigned long value );
37unsigned long readdw( unsigned long addr );
38unsigned long readfb( unsigned long addr );
39unsigned long writefb( unsigned long addr, unsigned long value );
40void writescan( unsigned long scan, unsigned long color );
41
42static int GetTileAperturePitch(unsigned long dwWidth, unsigned long dwBpp);
43void SavageSetGBD_M7(ScrnInfoPtr pScrn);
44void SavageSetGBD_3D(ScrnInfoPtr pScrn);
45void SavageSetGBD_Twister(ScrnInfoPtr pScrn);
46void SavageSetGBD_PM(ScrnInfoPtr pScrn);
47void SavageSetGBD_2000(ScrnInfoPtr pScrn);
48
49/*
50 * This is used to cache the last known value for routines we want to
51 * call from the debugger.
52 */
53
54ScrnInfoPtr gpScrn = 0;
55
56/*
57 *  returns the aperture pitch for tiled mode.
58 *  if MM850C_15 = 0 (use NB linear tile mode) the pitch is screen stride aligned to 128bytes
59 *  if MM850C_15 = 1 (use MS-1 128bit non-linear tile mode),we should do it as follows
60 *  we now only support the later, and don't use Y range flag,see tile surface register
61*/
62static int GetTileAperturePitch(unsigned long dwWidth, unsigned long dwBpp)
63{
64    switch (dwBpp) {
65        case 4:
66        case 8:
67            return(0x2000);
68            break;
69        case 16:
70            return(0x1000);
71            break;
72        case 32:
73            return(0x2000);
74            break;
75        default:
76            return(0x2000);
77    }
78}
79
80static int GetTileAperturePitch2000(unsigned long dwWidth, unsigned long dwBpp, int lDelta)
81{
82    switch (dwBpp) {
83        case 4:
84        case 8:
85            return(0x2000);
86            break;
87        case 16:
88	    if (lDelta > 0x800)
89                return(0x1000);
90	    else
91	        return(0x800);
92            break;
93        case 32:
94	    if (lDelta > 0x1000)
95                return(0x2000);
96	    else
97	        return(0x1000);
98            break;
99        default:
100            return(0x2000);
101    }
102}
103
104void
105SavageInitialize2DEngine(ScrnInfoPtr pScrn)
106{
107    vgaHWPtr hwp = VGAHWPTR(pScrn);
108    SavagePtr psav = SAVPTR(pScrn);
109    unsigned int vgaCRIndex = hwp->IOBase + 4;
110    unsigned int vgaCRReg = hwp->IOBase + 5;
111
112    gpScrn = pScrn;
113
114    VGAOUT16(vgaCRIndex, 0x0140);
115    VGAOUT8(vgaCRIndex, 0x31);
116    VGAOUT8(vgaCRReg, 0x0c);
117
118    /* Setup plane masks */
119    OUTREG(0x8128, ~0); /* enable all write planes */
120    OUTREG(0x812C, ~0); /* enable all read planes */
121    OUTREG16(0x8134, 0x27);
122    OUTREG16(0x8136, 0x07);
123
124    switch( psav->Chipset ) {
125
126    case S3_SAVAGE3D:
127    case S3_SAVAGE_MX:
128	/* Disable BCI */
129	OUTREG(0x48C18, INREG(0x48C18) & 0x3FF0);
130	/* Setup BCI command overflow buffer */
131	OUTREG(0x48C14, (psav->cobOffset >> 11) | (psav->cobIndex << 29)); /* tim */
132    	/*OUTREG(S3_OVERFLOW_BUFFER, psav->cobOffset >> 11 | 0xE0000000);*/ /* S3 */
133	/* Program shadow status update. */
134	{
135	    unsigned long thresholds = ((psav->bciThresholdLo & 0xffff) << 16) |
136		(psav->bciThresholdHi & 0xffff);
137	    OUTREG(0x48C10, thresholds);
138	    /* used to be 0x78207220 */
139	}
140	if( psav->ShadowStatus )
141	{
142	    OUTREG(0x48C0C, psav->ShadowPhysical | 1 );
143	    /* Enable BCI and command overflow buffer */
144	    OUTREG(0x48C18, INREG(0x48C18) | 0x0E);
145	}
146	else
147	{
148	    OUTREG(0x48C0C, 0);
149	    /* Enable BCI and command overflow buffer */
150	    OUTREG(0x48C18, INREG(0x48C18) | 0x0C);
151	}
152	break;
153
154    case S3_SAVAGE4:
155    case S3_TWISTER:
156    case S3_PROSAVAGE:
157    case S3_PROSAVAGEDDR:
158    case S3_SUPERSAVAGE:
159	/* Disable BCI */
160	OUTREG(0x48C18, INREG(0x48C18) & 0x3FF0);
161	if (!psav->disableCOB) {
162	    /* Setup BCI command overflow buffer */
163	    OUTREG(0x48C14, (psav->cobOffset >> 11) | (psav->cobIndex << 29));
164	}
165	/* Program shadow status update */ /* AGD: what should this be? */
166	{
167	    unsigned long thresholds = ((psav->bciThresholdLo & 0x1fffe0) << 11) |
168		((psav->bciThresholdHi & 0x1fffe0) >> 5);
169	    OUTREG(0x48C10, thresholds);
170	}
171	/*OUTREG(0x48C10, 0x00700040);*/ /* tim */
172        /*OUTREG(0x48C10, 0x0e440f04L);*/ /* S3 */
173	if( psav->ShadowStatus )
174	{
175	    OUTREG(0x48C0C, psav->ShadowPhysical | 1 );
176	    if (psav->disableCOB) {
177	    	/* Enable BCI without the COB */
178		OUTREG(0x48C18, INREG(0x48C18) | 0x0a);
179	    } else {
180		OUTREG32(0x48C18, INREG32(0x48C18) | 0x0E);
181	    }
182	}
183	else
184	{
185	    OUTREG(0x48C0C, 0);
186	    if (psav->disableCOB) {
187	    	/* Enable BCI without the COB */
188	    	OUTREG(0x48C18, INREG(0x48C18) | 0x08);
189	    } else {
190		OUTREG32(0x48C18, INREG32(0x48C18) | 0x0C);
191	    }
192	}
193	break;
194
195    case S3_SAVAGE2000:
196	/* Disable BCI */
197	OUTREG(0x48C18, 0);
198	/* Setup BCI command overflow buffer */
199	OUTREG(0x48C18, (psav->cobOffset >> 7) | (psav->cobIndex));
200	if( psav->ShadowStatus )
201	{
202	    /* Set shadow update thresholds. */
203	    /*OUTREG(0x48C10, 0x6090 );
204	      OUTREG(0x48C14, 0x70A8 );*/
205	    OUTREG(0x48C10, psav->bciThresholdLo >> 2);
206	    OUTREG(0x48C14, psav->bciThresholdHi >> 2);
207	    /* Enable shadow status update */
208	    OUTREG(0x48A30, psav->ShadowPhysical );
209	    /* Enable BCI, command overflow buffer and shadow status. */
210	    OUTREG(0x48C18, INREG(0x48C18) | 0x00380000 );
211	}
212	else
213	{
214	    /* Disable shadow status update */
215	    OUTREG(0x48A30, 0);
216	    /* Enable BCI and command overflow buffer */
217	    OUTREG(0x48C18, INREG(0x48C18) | 0x00280000 );
218	}
219	break;
220    }
221
222    /* Use and set global bitmap descriptor. */
223
224    /* For reasons I do not fully understand yet, on the Savage4, the */
225    /* write to the GBD register, MM816C, does not "take" at this time. */
226    /* Only the low-order byte is acknowledged, resulting in an incorrect */
227    /* stride.  Writing the register later, after the mode switch, works */
228    /* correctly.  This needs to get resolved. */
229
230    SavageSetGBD(pScrn);
231}
232
233void
234SavageSetGBD(ScrnInfoPtr pScrn)
235{
236    SavagePtr psav = SAVPTR(pScrn);
237
238    UnProtectCRTC();
239    UnLockExtRegs();
240    VerticalRetraceWait();
241
242    psav->lDelta = pScrn->virtualX * (pScrn->bitsPerPixel >> 3);
243
244    /*
245     * we can use Option "DisableTile" "TRUE" to disable tile mode
246     * if don't disable tile,we only support tile mode under 16/32bpp
247     */
248    if ((!psav->bDisableTile) && ((pScrn->bitsPerPixel == 16) || (pScrn->bitsPerPixel == 32))) {
249        /* tileing in 16/32 BPP */
250        psav->bTiled = TRUE;
251        psav->lDelta = ((psav->lDelta + 127) >> 7) << 7;
252
253        if (S3_SAVAGE3D_SERIES(psav->Chipset))
254            psav->ulAperturePitch = 0x2000;
255	else if (psav->Chipset == S3_SAVAGE2000)
256	    psav->ulAperturePitch = GetTileAperturePitch2000(pScrn->virtualX,
257							     pScrn->bitsPerPixel,
258							     psav->lDelta);
259        else
260            psav->ulAperturePitch = GetTileAperturePitch(pScrn->virtualX,pScrn->bitsPerPixel);
261
262        /* Use the aperture for linear screen */
263        psav->FBStart = psav->ApertureMap;
264    } else {
265        psav->bTiled = FALSE;
266        /* 32: Alignment for nontiled mode */
267        psav->lDelta = ((psav->lDelta + 31) >> 5) << 5;
268        psav->ulAperturePitch = psav->lDelta;
269    }
270
271    psav->Bpp = pScrn->bitsPerPixel >> 3;
272    psav->cxMemory = psav->lDelta / (psav->Bpp);
273    psav->cyMemory = psav->endfb / psav->lDelta - 1;
274    /* ??????????? */
275    if (psav->cyMemory > 2048)
276        psav->cyMemory = 2048;
277
278    /*
279     * If tiling, adjust down psav->cyMemory to the last multiple
280     * of a tileheight, so that we don't try to use partial tiles.
281     */
282    if (psav->bTiled)  {
283        psav->cyMemory -= (psav->cyMemory % 16);
284    }
285
286    /*
287     *  Initialization per GX-3.
288     *
289     *  1. MM48C18 - Disable BCI.
290     *  2. MM48C0C - Enable updating shadow status
291     *              and initialize shadow memory address.
292     *  2b. MM48C18 - bit 1 = 1, Enable Command Buffer status updates
293     *              (S3_OVERFLOW_BUFFER_PTR)
294     *  3. MM48C10 - Initialize command buffer threshold
295     *              (S3_BUFFER_THRESHOLD)
296     *  4. MM48C14 - Setup command buffer offset and size
297     *              (S3_OVERFLOW_BUFFER)
298     *  5. MM816C  - Enable BCI.
299     *  6. MM48C40 - Setup tiled surface 0 register.
300     *  7. CR31 - bit 0 = 0, Disable address offset bits(CR6A_6-0).
301     *  8. CR50 - bit 7,6,0 = 111, Use Global Bitmap Descriptor.
302     *  9. CR88 - bit 4 = 0, Block write on (linear mode) IFF we know we
303     *                       have the right kind of SGRAM memory,
304     *                       bit 4 = 1, Block write off (always off if tiling)
305     *  10.CR69 - Bit 7 = 1, MM81C0 and 81C4 are used to control
306     *                       primary stream.
307     *  11.MM8128, MM812c - Setup read/write mask registers
308     *  12.MM816C, MM8168 - Set up Global Bitmap Descriptor 1 and 2.
309     */
310    switch (psav->Chipset) {
311        case S3_SAVAGE3D:
312	    SavageSetGBD_3D(pScrn);
313	    break;
314        case S3_SAVAGE_MX:
315            SavageSetGBD_M7(pScrn);
316            break;
317        case S3_SAVAGE4:
318        case S3_TWISTER:
319        case S3_PROSAVAGE:
320        case S3_PROSAVAGEDDR:
321            SavageSetGBD_Twister(pScrn);
322            break;
323        case S3_SUPERSAVAGE:
324            SavageSetGBD_PM(pScrn);
325            break;
326        case S3_SAVAGE2000:
327	    SavageSetGBD_2000(pScrn);
328	    break;
329    }
330}
331
332void SavageSetGBD_Twister(ScrnInfoPtr pScrn)
333{
334    SavagePtr psav = SAVPTR(pScrn);
335    unsigned long       ulTmp;
336    unsigned char byte;
337    int bci_enable, tile16, tile32;
338
339    if (psav->Chipset == S3_SAVAGE4) {
340	bci_enable = BCI_ENABLE;
341	tile16 = TILE_FORMAT_16BPP;
342	tile32 = TILE_FORMAT_32BPP;
343    } else {
344	bci_enable = BCI_ENABLE_TWISTER;
345	tile16 = TILE_DESTINATION;
346	tile32 = TILE_DESTINATION;
347    }
348
349    /* MM81C0 and 81C4 are used to control primary stream. */
350    OUTREG32(PSTREAM_FBADDR0_REG,0x00000000);
351    OUTREG32(PSTREAM_FBADDR1_REG,0x00000000);
352
353    /*
354     *  Program Primary Stream Stride Register.
355     *
356     *  Tell engine if tiling on or off, set primary stream stride, and
357     *  if tiling, set tiling bits/pixel and primary stream tile offset.
358     *  Note that tile offset (bits 16 - 29) must be scanline width in
359     *  bytes/128bytespertile * 256 Qwords/tile.  This is equivalent to
360     *  lDelta * 2.  Remember that if tiling, lDelta is screenwidth in
361     *  bytes padded up to an even number of tilewidths.
362     */
363    if (!psav->bTiled) {
364        OUTREG32(PSTREAM_STRIDE_REG,
365                 (((psav->lDelta * 2) << 16) & 0x3FFFE000) |
366                 (psav->lDelta & 0x00001fff));
367    }
368    else if (pScrn->bitsPerPixel == 16) {
369        /* Scanline-length-in-bytes/128-bytes-per-tile * 256 Qwords/tile */
370        OUTREG32(PSTREAM_STRIDE_REG,
371                 (((psav->lDelta * 2) << 16) & 0x3FFFE000)
372                 | 0x80000000 | (psav->lDelta & 0x00001fff));
373    }
374    else if (pScrn->bitsPerPixel == 32) {
375        OUTREG32(PSTREAM_STRIDE_REG,
376                 (((psav->lDelta * 2) << 16) & 0x3FFFE000)
377                 | 0xC0000000 | (psav->lDelta & 0x00001fff));
378    }
379
380    /*
381     *  CR69, bit 7 = 1
382     *  to use MM streams processor registers to control primary stream.
383     */
384    OUTREG8(CRT_ADDRESS_REG,0x69);
385    byte = INREG8(CRT_DATA_REG) | 0x80;
386    OUTREG8(CRT_DATA_REG,byte);
387
388    OUTREG32(0x8128, 0xFFFFFFFFL);
389    OUTREG32(0x812C, 0xFFFFFFFFL);
390
391    OUTREG32(S3_BCI_GLB_BD_HIGH, bci_enable | S3_LITTLE_ENDIAN | S3_BD64);
392
393
394    /* CR50, bit 7,6,0 = 111, Use GBD.*/
395    OUTREG8(CRT_ADDRESS_REG,0x50);
396    byte = INREG8(CRT_DATA_REG) | 0xC1;
397    OUTREG8(CRT_DATA_REG, byte);
398
399    /*
400     * if MS1NB style linear tiling mode.
401     * bit MM850C[15] = 0 select NB linear tile mode.
402     * bit MM850C[15] = 1 select MS-1 128-bit non-linear tile mode.
403     */
404    ulTmp = INREG32(ADVANCED_FUNC_CTRL) | 0x8000; /* use MS-s style tile mode*/
405    OUTREG32(ADVANCED_FUNC_CTRL,ulTmp);
406
407    /*
408     * Set up Tiled Surface Registers
409     *  Bit 25:20 - Surface width in tiles.
410     *  Bit 29 - Y Range Flag.
411     *  Bit 31:30 = 00, 4 bpp.
412     *            = 01, 8 bpp.
413     *            = 10, 16 bpp.
414     *            = 11, 32 bpp.
415     */
416    /*
417     * Global Bitmap Descriptor Register MM816C - twister/prosavage
418     *   bit 24~25: tile format
419     *          00: linear
420     *          01: destination tiling format
421     *          10: texture tiling format
422     *          11: reserved
423     *   bit 28: block write disable/enable
424     *          0: disable
425     *          1: enable
426     */
427    /*
428     * Global Bitmap Descriptor Register MM816C - savage4
429     *   bit 24~25: tile format
430     *          00: linear
431     *          01: reserved
432     *          10: 16 bpp tiles
433     *          11: 32 bpp tiles
434     *   bit 28: block write disable/enable
435     *          0: enable
436     *          1: disable
437     */
438    if (!psav->bTiled) {
439        /*
440         *  Do not enable block_write even for non-tiling modes, because
441         *  the driver cannot determine if the memory type is the certain
442         *  type of SGRAM for which block_write can be used.
443         */
444        psav->GlobalBD.bd1.HighPart.ResBWTile = TILE_FORMAT_LINEAR;/* linear */
445    }
446    else if (pScrn->bitsPerPixel == 16) {
447	psav->GlobalBD.bd1.HighPart.ResBWTile = tile16; /* 16 bpp/destination tiling format */
448
449        ulTmp = (((pScrn->virtualX + 0x3F) & 0x0000FFC0) >> 6) << 20;
450        OUTREG32(TILED_SURFACE_REGISTER_0,ulTmp | TILED_SURF_BPP16);
451    }
452    else if (pScrn->bitsPerPixel == 32) {
453        psav->GlobalBD.bd1.HighPart.ResBWTile = tile32; /* 32 bpp/destination tiling format */
454
455        ulTmp = ( ((pScrn->virtualX + 0x1F) & 0x0000FFE0) >> 5) << 20;
456        OUTREG32(TILED_SURFACE_REGISTER_0,ulTmp | TILED_SURF_BPP32);
457    }
458
459    psav->GlobalBD.bd1.HighPart.ResBWTile |= 0x10;/* disable block write - was 0 */
460    /* HW uses width */
461    psav->GlobalBD.bd1.HighPart.Stride = (unsigned short) psav->lDelta / (pScrn->bitsPerPixel >> 3);
462    psav->GlobalBD.bd1.HighPart.Bpp = (unsigned char) (pScrn->bitsPerPixel);
463    psav->GlobalBD.bd1.Offset = pScrn->fbOffset;
464
465
466    /*
467     * CR88, bit 4 - Block write enabled/disabled.
468     *
469     *      Note: Block write must be disabled when writing to tiled
470     *            memory.  Even when writing to non-tiled memory, block
471     *            write should only be enabled for certain types of SGRAM.
472     */
473    OUTREG8(CRT_ADDRESS_REG,0x88);
474    byte = INREG8(CRT_DATA_REG) | DISABLE_BLOCK_WRITE_2D;
475    OUTREG8(CRT_DATA_REG,byte);
476
477    /*
478     * CR31, bit 0 = 0, Disable address offset bits(CR6A_6-0).
479     *       bit 0 = 1, Enable 8 Mbytes of display memory thru 64K window
480     *                  at A000:0.
481     */
482    OUTREG8(CRT_ADDRESS_REG,MEMORY_CONFIG_REG); /* cr31 */
483    byte = INREG8(CRT_DATA_REG) & (~(ENABLE_CPUA_BASE_A0000));
484    OUTREG8(CRT_DATA_REG,byte); /* perhaps this should be 0x0c */
485
486    /* turn on screen */
487    OUTREG8(SEQ_ADDRESS_REG,0x01);
488    byte = INREG8(SEQ_DATA_REG) & ~0x20;
489    OUTREG8(SEQ_DATA_REG,byte);
490
491    /* program the GBD and SBD's */
492    OUTREG32(S3_GLB_BD_LOW,psav->GlobalBD.bd2.LoPart);
493    OUTREG32(S3_GLB_BD_HIGH,psav->GlobalBD.bd2.HiPart | bci_enable | S3_LITTLE_ENDIAN | S3_BD64);
494    OUTREG32(S3_PRI_BD_LOW,psav->GlobalBD.bd2.LoPart);
495    OUTREG32(S3_PRI_BD_HIGH,psav->GlobalBD.bd2.HiPart);
496    OUTREG32(S3_SEC_BD_LOW,psav->GlobalBD.bd2.LoPart);
497    OUTREG32(S3_SEC_BD_HIGH,psav->GlobalBD.bd2.HiPart);
498}
499
500void SavageSetGBD_3D(ScrnInfoPtr pScrn)
501{
502    SavagePtr psav = SAVPTR(pScrn);
503    unsigned long       ulTmp;
504    unsigned char byte;
505    int bci_enable, tile16, tile32;
506
507    bci_enable = BCI_ENABLE;
508    tile16 = TILE_FORMAT_16BPP;
509    tile32 = TILE_FORMAT_32BPP;
510
511    /* MM81C0 and 81C4 are used to control primary stream. */
512    OUTREG32(PSTREAM_FBADDR0_REG,0x00000000);
513    OUTREG32(PSTREAM_FBADDR1_REG,0x00000000);
514
515    /*
516     *  Program Primary Stream Stride Register.
517     *
518     *  Tell engine if tiling on or off, set primary stream stride, and
519     *  if tiling, set tiling bits/pixel and primary stream tile offset.
520     *  Note that tile offset (bits 16 - 29) must be scanline width in
521     *  bytes/128bytespertile * 256 Qwords/tile.  This is equivalent to
522     *  lDelta * 2.  Remember that if tiling, lDelta is screenwidth in
523     *  bytes padded up to an even number of tilewidths.
524     */
525    if (!psav->bTiled) {
526        OUTREG32(PSTREAM_STRIDE_REG,
527                 (((psav->lDelta * 2) << 16) & 0x3FFFE000) |
528                 (psav->lDelta & 0x00001fff));
529    }
530    else if (pScrn->bitsPerPixel == 16) {
531        /* Scanline-length-in-bytes/128-bytes-per-tile * 256 Qwords/tile */
532        OUTREG32(PSTREAM_STRIDE_REG,
533                 (((psav->lDelta * 2) << 16) & 0x3FFFE000)
534                 | 0x80000000 | (psav->lDelta & 0x00001fff));
535    }
536    else if (pScrn->bitsPerPixel == 32) {
537        OUTREG32(PSTREAM_STRIDE_REG,
538                 (((psav->lDelta * 2) << 16) & 0x3FFFE000)
539                 | 0xC0000000 | (psav->lDelta & 0x00001fff));
540    }
541
542    /*
543     *  CR69, bit 7 = 1
544     *  to use MM streams processor registers to control primary stream.
545     */
546    OUTREG8(CRT_ADDRESS_REG,0x69);
547    byte = INREG8(CRT_DATA_REG) | 0x80;
548    OUTREG8(CRT_DATA_REG,byte);
549
550    OUTREG32(0x8128, 0xFFFFFFFFL);
551    OUTREG32(0x812C, 0xFFFFFFFFL);
552
553    OUTREG32(S3_BCI_GLB_BD_HIGH, bci_enable | S3_LITTLE_ENDIAN | S3_BD64);
554
555
556    /* CR50, bit 7,6,0 = 111, Use GBD.*/
557    OUTREG8(CRT_ADDRESS_REG,0x50);
558    byte = INREG8(CRT_DATA_REG) | 0xC1;
559    OUTREG8(CRT_DATA_REG, byte);
560
561    /*
562     * if MS1NB style linear tiling mode.
563     * bit MM850C[15] = 0 select NB linear tile mode.
564     * bit MM850C[15] = 1 select MS-1 128-bit non-linear tile mode.
565     */
566    ulTmp = INREG32(ADVANCED_FUNC_CTRL) | 0x8000; /* use MS-s style tile mode*/
567    OUTREG32(ADVANCED_FUNC_CTRL,ulTmp);
568
569    /*
570     * Tiled Surface 0 Registers MM48C40:
571     *  bit 0~23: tile surface 0 frame buffer offset
572     *  bit 24~29:tile surface 0 width
573     *  bit 30~31:tile surface 0 bits/pixel
574     *            00: reserved
575     *            01, 8 bits
576     *            10, 16 Bits.
577     *            11, 32 Bits.
578     */
579    /*
580     * Global Bitmap Descriptor Register MM816C
581     *   bit 24~25: tile format
582     *          00: linear
583     *          01: reserved
584     *          10: 16 bpp tiles
585     *          11: 32 bpp tiles
586     *   bit 28: block write disable/enable
587     *          0: enable
588     *          1: disable
589     */
590    if (!psav->bTiled) {
591        /*
592         *  Do not enable block_write even for non-tiling modes, because
593         *  the driver cannot determine if the memory type is the certain
594         *  type of SGRAM for which block_write can be used.
595         */
596        psav->GlobalBD.bd1.HighPart.ResBWTile = TILE_FORMAT_LINEAR;/* linear */
597    }
598    else if (pScrn->bitsPerPixel == 16) {
599	psav->GlobalBD.bd1.HighPart.ResBWTile = tile16; /* 16 bpp/destination tiling format */
600
601        ulTmp = (((pScrn->virtualX + 0x3F) & 0x0000FFC0) >> 6) << 24;
602        OUTREG32(TILED_SURFACE_REGISTER_0,ulTmp | TILED_SURF_BPP16);
603    }
604    else if (pScrn->bitsPerPixel == 32) {
605        psav->GlobalBD.bd1.HighPart.ResBWTile = tile32; /* 32 bpp/destination tiling format */
606
607        ulTmp = ( ((pScrn->virtualX + 0x1F) & 0x0000FFE0) >> 5) << 24;
608        OUTREG32(TILED_SURFACE_REGISTER_0,ulTmp | TILED_SURF_BPP32);
609    }
610
611    psav->GlobalBD.bd1.HighPart.ResBWTile |= 0x10;/* disable block write - was 0 */
612    /* HW uses width */
613    psav->GlobalBD.bd1.HighPart.Stride = (unsigned short) psav->lDelta / (pScrn->bitsPerPixel >> 3);
614    psav->GlobalBD.bd1.HighPart.Bpp = (unsigned char) (pScrn->bitsPerPixel);
615    psav->GlobalBD.bd1.Offset = pScrn->fbOffset;
616
617
618    /*
619     * CR88, bit 4 - Block write enabled/disabled.
620     *
621     *      Note: Block write must be disabled when writing to tiled
622     *            memory.  Even when writing to non-tiled memory, block
623     *            write should only be enabled for certain types of SGRAM.
624     */
625    OUTREG8(CRT_ADDRESS_REG,0x88);
626    byte = INREG8(CRT_DATA_REG) | DISABLE_BLOCK_WRITE_2D;
627    OUTREG8(CRT_DATA_REG,byte);
628
629    /*
630     * CR31, bit 0 = 0, Disable address offset bits(CR6A_6-0).
631     *       bit 0 = 1, Enable 8 Mbytes of display memory thru 64K window
632     *                  at A000:0.
633     */
634    OUTREG8(CRT_ADDRESS_REG,MEMORY_CONFIG_REG); /* cr31 */
635    byte = INREG8(CRT_DATA_REG) & (~(ENABLE_CPUA_BASE_A0000));
636    OUTREG8(CRT_DATA_REG,byte); /* perhaps this should be 0x0c */
637
638    /* turn on screen */
639    OUTREG8(SEQ_ADDRESS_REG,0x01);
640    byte = INREG8(SEQ_DATA_REG) & ~0x20;
641    OUTREG8(SEQ_DATA_REG,byte);
642
643    /* program the GBD and SBD's */
644    OUTREG32(S3_GLB_BD_LOW,psav->GlobalBD.bd2.LoPart);
645    OUTREG32(S3_GLB_BD_HIGH,psav->GlobalBD.bd2.HiPart | bci_enable | S3_LITTLE_ENDIAN | S3_BD64);
646    OUTREG32(S3_PRI_BD_LOW,psav->GlobalBD.bd2.LoPart);
647    OUTREG32(S3_PRI_BD_HIGH,psav->GlobalBD.bd2.HiPart);
648    OUTREG32(S3_SEC_BD_LOW,psav->GlobalBD.bd2.LoPart);
649    OUTREG32(S3_SEC_BD_HIGH,psav->GlobalBD.bd2.HiPart);
650}
651
652void SavageSetGBD_M7(ScrnInfoPtr pScrn)
653{
654    SavagePtr psav = SAVPTR(pScrn);
655    unsigned long ulTmp;
656    unsigned char byte;
657    int bci_enable, tile16, tile32;
658
659    bci_enable = BCI_ENABLE;
660    tile16 = TILE_FORMAT_16BPP;
661    tile32 = TILE_FORMAT_32BPP;
662
663
664    /* following is the enable case */
665
666    /* SR01:turn off screen */
667    OUTREG8 (SEQ_ADDRESS_REG,0x01);
668    byte = INREG8(SEQ_DATA_REG) | 0x20;
669    OUTREG8(SEQ_DATA_REG,byte);
670
671    /*
672     * CR67_3:
673     *  = 1  stream processor MMIO address and stride register
674     *       are used to control the primary stream
675     *  = 0  standard VGA address and stride registers
676     *       are used to control the primary streams
677     */
678    if (psav->IsPrimary) {
679    	OUTREG8(CRT_ADDRESS_REG,0x67);
680    	byte =  INREG8(CRT_DATA_REG) | 0x08;
681    	OUTREG8(CRT_DATA_REG,byte);
682    } else if (psav->IsSecondary) {
683    	/* IGA 2 */
684    	OUTREG16(SEQ_ADDRESS_REG,SELECT_IGA2_READS_WRITES);
685
686    	OUTREG8(CRT_ADDRESS_REG,0x67);
687    	byte =  INREG8(CRT_DATA_REG) | 0x08;
688    	OUTREG8(CRT_DATA_REG,byte);
689
690    	OUTREG16(SEQ_ADDRESS_REG,SELECT_IGA1);
691    } else {
692    	OUTREG8(CRT_ADDRESS_REG,0x67);
693    	byte =  INREG8(CRT_DATA_REG) | 0x08;
694    	OUTREG8(CRT_DATA_REG,byte);
695    	/* IGA 2 */
696    	OUTREG16(SEQ_ADDRESS_REG,SELECT_IGA2_READS_WRITES);
697    	OUTREG8(CRT_ADDRESS_REG,0x67);
698    	byte =  INREG8(CRT_DATA_REG) | 0x08;
699    	OUTREG8(CRT_DATA_REG,byte);
700    	OUTREG16(SEQ_ADDRESS_REG,SELECT_IGA1);
701    }
702    /* Set primary stream to bank 0 */
703    OUTREG8(CRT_ADDRESS_REG, MEMORY_CTRL0_REG);/* CRCA */
704    byte =  INREG8(CRT_DATA_REG) & ~(MEM_PS1 + MEM_PS2) ;
705    OUTREG8(CRT_DATA_REG,byte);
706#if 0
707    /*
708     * if we have 8MB of frame buffer here then we must really be a 16MB
709     * card and that means that the second device is always in the upper
710     * bank of memory (MHS)
711     */
712    if (psav->videoRambytes >= 0x800000) {
713        /* 16MB Video Memory cursor is at the end in Bank 1 */
714        byte |= 0x3;
715        OUTREG16(CRT_ADDRESS_REG, (byte << 8) | MEMORY_CTRL0_REG);
716    }
717#endif
718
719    /* MM81C0 and 81C4 are used to control primary stream. */
720    if (psav->IsPrimary) {
721    	OUTREG32(PRI_STREAM_FBUF_ADDR0,pScrn->fbOffset & 0x7fffff);
722    	OUTREG32(PRI_STREAM_FBUF_ADDR1,pScrn->fbOffset & 0x7fffff);
723    } else if (psav->IsSecondary) {
724    	OUTREG32(PRI_STREAM2_FBUF_ADDR0,pScrn->fbOffset & 0x7fffff);
725    	OUTREG32(PRI_STREAM2_FBUF_ADDR1,pScrn->fbOffset & 0x7fffff);
726    } else {
727    	OUTREG32(PRI_STREAM_FBUF_ADDR0,pScrn->fbOffset & 0x7fffff);
728    	OUTREG32(PRI_STREAM_FBUF_ADDR1,pScrn->fbOffset & 0x7fffff);
729    	OUTREG32(PRI_STREAM2_FBUF_ADDR0,pScrn->fbOffset & 0x7fffff);
730    	OUTREG32(PRI_STREAM2_FBUF_ADDR1,pScrn->fbOffset & 0x7fffff);
731    }
732
733    /*
734     *  Program Primary Stream Stride Register.
735     *
736     *  Tell engine if tiling on or off, set primary stream stride, and
737     *  if tiling, set tiling bits/pixel and primary stream tile offset.
738     *  Note that tile offset (bits 16 - 29) must be scanline width in
739     *  bytes/128bytespertile * 256 Qwords/tile.  This is equivalent to
740     *  lDelta * 2.  Remember that if tiling, lDelta is screenwidth in
741     *  bytes padded up to an even number of tilewidths.
742     */
743    if (!psav->bTiled) {
744 	if (psav->IsPrimary) {
745            OUTREG32(PRI_STREAM_STRIDE,
746                 (((psav->lDelta * 2) << 16) & 0x3FFF0000) |
747                 (psav->lDelta & 0x00003fff));
748	} else if (psav->IsSecondary) {
749            OUTREG32(PRI_STREAM2_STRIDE,
750                 (((psav->lDelta * 2) << 16) & 0x3FFF0000) |
751                 (psav->lDelta & 0x00003fff));
752	} else {
753            OUTREG32(PRI_STREAM_STRIDE,
754                 (((psav->lDelta * 2) << 16) & 0x3FFF0000) |
755                 (psav->lDelta & 0x00003fff));
756            OUTREG32(PRI_STREAM2_STRIDE,
757                 (((psav->lDelta * 2) << 16) & 0x3FFF0000) |
758                 (psav->lDelta & 0x00003fff));
759	}
760
761    } else if (pScrn->bitsPerPixel == 16) {
762        /* Scanline-length-in-bytes/128-bytes-per-tile * 256 Qwords/tile */
763	if (psav->IsPrimary) {
764            OUTREG32(PRI_STREAM_STRIDE,
765                 (((psav->lDelta * 2) << 16) & 0x3FFF0000)
766                 | 0x80000000 | (psav->lDelta & 0x00003fff));
767        } else if (psav->IsSecondary) {
768            OUTREG32(PRI_STREAM2_STRIDE,
769                 (((psav->lDelta * 2) << 16) & 0x3FFF0000)
770                 | 0x80000000 | (psav->lDelta & 0x00003fff));
771        } else {
772            OUTREG32(PRI_STREAM_STRIDE,
773                 (((psav->lDelta * 2) << 16) & 0x3FFF0000)
774                 | 0x80000000 | (psav->lDelta & 0x00003fff));
775            OUTREG32(PRI_STREAM2_STRIDE,
776                 (((psav->lDelta * 2) << 16) & 0x3FFF0000)
777                 | 0x80000000 | (psav->lDelta & 0x00003fff));
778	}
779
780    } else if (pScrn->bitsPerPixel == 32) {
781	if (psav->IsPrimary) {
782            OUTREG32(PRI_STREAM_STRIDE,
783                 (((psav->lDelta * 2) << 16) & 0x3FFF0000)
784                 | 0xC0000000 | (psav->lDelta & 0x00003fff));
785	} else if (psav->IsSecondary) {
786            OUTREG32(PRI_STREAM2_STRIDE,
787                 (((psav->lDelta * 2) << 16) & 0x3FFF0000)
788                 | 0xC0000000 | (psav->lDelta & 0x00003fff));
789	} else {
790            OUTREG32(PRI_STREAM_STRIDE,
791                 (((psav->lDelta * 2) << 16) & 0x3FFF0000)
792                 | 0xC0000000 | (psav->lDelta & 0x00003fff));
793            OUTREG32(PRI_STREAM2_STRIDE,
794                 (((psav->lDelta * 2) << 16) & 0x3FFF0000)
795                 | 0xC0000000 | (psav->lDelta & 0x00003fff));
796	}
797    }
798
799    OUTREG32(0x8128, 0xFFFFFFFFL);
800    OUTREG32(0x812C, 0xFFFFFFFFL);
801
802    if (!psav->IsSecondary)
803    	OUTREG32(S3_BCI_GLB_BD_HIGH, bci_enable | S3_LITTLE_ENDIAN | S3_BD64);
804
805    /* CR50, bit 7,6,0 = 111, Use GBD.*/
806    OUTREG8(CRT_ADDRESS_REG,0x50);
807    byte = INREG8(CRT_DATA_REG) | 0xC1;
808    OUTREG8(CRT_DATA_REG, byte);
809
810    /*
811     * CR78, bit 3  - Block write enabled(1)/disabled(0).
812     *       bit 2  - Block write cycle time(0:2 cycles,1: 1 cycle)
813     *      Note: Block write must be disabled when writing to tiled
814     *            memory.  Even when writing to non-tiled memory, block
815     *            write should only be enabled for certain types of SGRAM.
816     */
817    OUTREG8(CRT_ADDRESS_REG,0x78);
818    /*byte = INREG8(CRT_DATA_REG) & ~0x0C;*/
819    byte = INREG8(CRT_DATA_REG) | 0xfb;
820    OUTREG8(CRT_DATA_REG,byte);
821
822    /*
823     * Tiled Surface 0 Registers MM48C40:
824     *  bit 0~23: tile surface 0 frame buffer offset
825     *  bit 24~29:tile surface 0 width
826     *  bit 30~31:tile surface 0 bits/pixel
827     *            00: reserved
828     *            01, 8 bits
829     *            10, 16 Bits.
830     *            11, 32 Bits.
831     */
832    /*
833     * Global Bitmap Descriptor Register MM816C
834     *   bit 24~25: tile format
835     *          00: linear
836     *          01: reserved
837     *          10: 16 bit
838     *          11: 32 bit
839     *   bit 28: block write disable/enable
840     *          0: enable
841     *          1: disable
842     */
843    if (!psav->bTiled) {
844        /*
845         *  Do not enable block_write even for non-tiling modes, because
846         *  the driver cannot determine if the memory type is the certain
847         *  type of SGRAM for which block_write can be used.
848         */
849        psav->GlobalBD.bd1.HighPart.ResBWTile = TILE_FORMAT_LINEAR;/* linear */
850
851    }
852    else if (pScrn->bitsPerPixel == 16) {
853        psav->GlobalBD.bd1.HighPart.ResBWTile = tile16;/* 16 bit */
854
855	ulTmp =  ((psav->lDelta / 2) >> 6) << 24;
856	if (psav->IsSecondary)
857            OUTREG32(TILED_SURFACE_REGISTER_1,ulTmp | TILED_SURF_BPP16 | pScrn->fbOffset);
858	else
859            OUTREG32(TILED_SURFACE_REGISTER_0,ulTmp | TILED_SURF_BPP16 | pScrn->fbOffset);
860    }
861    else if (pScrn->bitsPerPixel == 32) {
862        psav->GlobalBD.bd1.HighPart.ResBWTile = tile32;/* 32 bit */
863
864	ulTmp =  ((psav->lDelta / 4) >> 5) << 24;
865	if (psav->IsSecondary)
866            OUTREG32(TILED_SURFACE_REGISTER_1,ulTmp | TILED_SURF_BPP32 | pScrn->fbOffset);
867	else
868            OUTREG32(TILED_SURFACE_REGISTER_0,ulTmp | TILED_SURF_BPP32 | pScrn->fbOffset);
869    }
870
871    psav->GlobalBD.bd1.HighPart.ResBWTile |= 0x10;/* disable block write */
872    /* HW uses width */
873    psav->GlobalBD.bd1.HighPart.Stride = (unsigned short)(psav->lDelta / (pScrn->bitsPerPixel >> 3));
874    psav->GlobalBD.bd1.HighPart.Bpp = (unsigned char) (pScrn->bitsPerPixel);
875    psav->GlobalBD.bd1.Offset = pScrn->fbOffset;
876
877
878    /*
879     * CR31, bit 0 = 0, Disable address offset bits(CR6A_6-0).
880     *       bit 0 = 1, Enable 8 Mbytes of display memory thru 64K window
881     *                  at A000:0.
882     */
883#if 0
884    OUTREG8(CRT_ADDRESS_REG,MEMORY_CONFIG_REG); /* cr31 */
885    byte = INREG8(CRT_DATA_REG) & (~(ENABLE_CPUA_BASE_A0000));
886    OUTREG8(CRT_DATA_REG,byte);
887#endif
888    OUTREG8(CRT_ADDRESS_REG,MEMORY_CONFIG_REG); /* cr31 */
889    byte = (INREG8(CRT_DATA_REG) | 0x04) & 0xFE;
890    OUTREG8(CRT_DATA_REG,byte);
891
892    if (!psav->IsSecondary) {
893    	/* program the GBD and SBD's */
894    	OUTREG32(S3_GLB_BD_LOW,psav->GlobalBD.bd2.LoPart );
895    	/* 8: bci enable */
896    	OUTREG32(S3_GLB_BD_HIGH,(psav->GlobalBD.bd2.HiPart
897                             | bci_enable | S3_LITTLE_ENDIAN | S3_BD64));
898    	OUTREG32(S3_PRI_BD_LOW,psav->GlobalBD.bd2.LoPart);
899    	OUTREG32(S3_PRI_BD_HIGH,psav->GlobalBD.bd2.HiPart);
900    	OUTREG32(S3_SEC_BD_LOW,psav->GlobalBD.bd2.LoPart);
901    	OUTREG32(S3_SEC_BD_HIGH,psav->GlobalBD.bd2.HiPart);
902    }
903
904    /* turn on screen */
905    OUTREG8(SEQ_ADDRESS_REG,0x01);
906    byte = INREG8(SEQ_DATA_REG) & ~0X20;
907    OUTREG8(SEQ_DATA_REG,byte);
908}
909
910void SavageSetGBD_PM(ScrnInfoPtr pScrn)
911{
912    SavagePtr psav = SAVPTR(pScrn);
913    unsigned long ulTmp;
914    unsigned char byte;
915    int bci_enable, tile16, tile32;
916
917
918    bci_enable = BCI_ENABLE_TWISTER;
919    tile16 = TILE_DESTINATION;
920    tile32 = TILE_DESTINATION;
921
922
923    /* following is the enable case */
924
925    /* SR01:turn off screen */
926    OUTREG8 (SEQ_ADDRESS_REG,0x01);
927    byte = INREG8(SEQ_DATA_REG) | 0x20;
928    OUTREG8(SEQ_DATA_REG,byte);
929
930    /*
931     * CR67_3:
932     *  = 1  stream processor MMIO address and stride register
933     *       are used to control the primary stream
934     *  = 0  standard VGA address and stride registers
935     *       are used to control the primary streams
936     */
937    if (psav->IsPrimary) {
938    	OUTREG8(CRT_ADDRESS_REG,0x67);
939    	byte =  INREG8(CRT_DATA_REG) | 0x08;
940    	OUTREG8(CRT_DATA_REG,byte);
941    } else if (psav->IsSecondary) {
942    	/* IGA 2 */
943    	OUTREG16(SEQ_ADDRESS_REG,SELECT_IGA2_READS_WRITES);
944
945    	OUTREG8(CRT_ADDRESS_REG,0x67);
946    	byte =  INREG8(CRT_DATA_REG) | 0x08;
947    	OUTREG8(CRT_DATA_REG,byte);
948
949    	OUTREG16(SEQ_ADDRESS_REG,SELECT_IGA1);
950    } else {
951    	OUTREG8(CRT_ADDRESS_REG,0x67);
952    	byte =  INREG8(CRT_DATA_REG) | 0x08;
953    	OUTREG8(CRT_DATA_REG,byte);
954    	/* IGA 2 */
955    	OUTREG16(SEQ_ADDRESS_REG,SELECT_IGA2_READS_WRITES);
956
957    	OUTREG8(CRT_ADDRESS_REG,0x67);
958    	byte =  INREG8(CRT_DATA_REG) | 0x08;
959    	OUTREG8(CRT_DATA_REG,byte);
960
961    	OUTREG16(SEQ_ADDRESS_REG,SELECT_IGA1);
962    }
963
964    /*
965     * load ps1 active registers as determined by MM81C0/81C4
966     * load ps2 active registers as determined by MM81B0/81B4
967     */
968    OUTREG8(CRT_ADDRESS_REG,0x65);
969    byte =  INREG8(CRT_DATA_REG) | 0x03;
970    OUTREG8(CRT_DATA_REG,byte);
971
972    /*
973     *  Program Primary Stream Stride Register.
974     *
975     *  Tell engine if tiling on or off, set primary stream stride, and
976     *  if tiling, set tiling bits/pixel and primary stream tile offset.
977     *  Note that tile offset (bits 16 - 29) must be scanline width in
978     *  bytes/128bytespertile * 256 Qwords/tile.  This is equivalent to
979     *  lDelta * 2.  Remember that if tiling, lDelta is screenwidth in
980     *  bytes padded up to an even number of tilewidths.
981     */
982    if (!psav->bTiled) {
983	if (psav->IsPrimary) {
984            OUTREG32(PRI_STREAM_STRIDE,
985                 (((psav->lDelta * 2) << 16) & 0x3FFF0000) |
986                 (psav->lDelta & 0x00001fff));
987	} else if (psav->IsSecondary) {
988            OUTREG32(PRI_STREAM2_STRIDE,
989                 (((psav->lDelta * 2) << 16) & 0x3FFF0000) |
990                 (psav->lDelta & 0x00001fff));
991	} else {
992            OUTREG32(PRI_STREAM_STRIDE,
993                 (((psav->lDelta * 2) << 16) & 0x3FFF0000) |
994                 (psav->lDelta & 0x00001fff));
995            OUTREG32(PRI_STREAM2_STRIDE,
996                 (((psav->lDelta * 2) << 16) & 0x3FFF0000) |
997                 (psav->lDelta & 0x00001fff));
998	}
999    } else if (pScrn->bitsPerPixel == 16) {
1000        /* Scanline-length-in-bytes/128-bytes-per-tile * 256 Qwords/tile */
1001	if (psav->IsPrimary) {
1002            OUTREG32(PRI_STREAM_STRIDE,
1003                 (((psav->lDelta * 2) << 16) & 0x3FFF0000)
1004                 | 0x80000000 | (psav->lDelta & 0x00001fff));
1005	} else if (psav->IsSecondary) {
1006            OUTREG32(PRI_STREAM2_STRIDE,
1007                 (((psav->lDelta * 2) << 16) & 0x3FFF0000)
1008                 | 0x80000000 | (psav->lDelta & 0x00001fff));
1009	} else {
1010            OUTREG32(PRI_STREAM_STRIDE,
1011                 (((psav->lDelta * 2) << 16) & 0x3FFF0000)
1012                 | 0x80000000 | (psav->lDelta & 0x00001fff));
1013            OUTREG32(PRI_STREAM2_STRIDE,
1014                 (((psav->lDelta * 2) << 16) & 0x3FFF0000)
1015                 | 0x80000000 | (psav->lDelta & 0x00001fff));
1016	}
1017
1018    } else if (pScrn->bitsPerPixel == 32) {
1019	if (psav->IsPrimary) {
1020            OUTREG32(PRI_STREAM_STRIDE,
1021                 (((psav->lDelta * 2) << 16) & 0x3FFF0000)
1022                 | 0xC0000000 | (psav->lDelta & 0x00001fff));
1023	} else if (psav->IsSecondary) {
1024            OUTREG32(PRI_STREAM2_STRIDE,
1025                 (((psav->lDelta * 2) << 16) & 0x3FFF0000)
1026                 | 0xC0000000 | (psav->lDelta & 0x00001fff));
1027	} else {
1028            OUTREG32(PRI_STREAM_STRIDE,
1029                 (((psav->lDelta * 2) << 16) & 0x3FFF0000)
1030                 | 0xC0000000 | (psav->lDelta & 0x00001fff));
1031            OUTREG32(PRI_STREAM2_STRIDE,
1032                 (((psav->lDelta * 2) << 16) & 0x3FFF0000)
1033                 | 0xC0000000 | (psav->lDelta & 0x00001fff));
1034	}
1035    }
1036
1037    /* MM81C0 and 81C4 are used to control primary stream. */
1038    if (psav->IsPrimary) {
1039        OUTREG32(PRI_STREAM_FBUF_ADDR0,pScrn->fbOffset);
1040        OUTREG32(PRI_STREAM_FBUF_ADDR1,0x80000000);
1041    } else if (psav->IsSecondary) {
1042        OUTREG32(PRI_STREAM2_FBUF_ADDR0,(pScrn->fbOffset & 0xfffffffc) | 0x80000000);
1043        OUTREG32(PRI_STREAM2_FBUF_ADDR1,pScrn->fbOffset & 0xffffffc);
1044    } else {
1045        OUTREG32(PRI_STREAM_FBUF_ADDR0,pScrn->fbOffset);
1046        OUTREG32(PRI_STREAM_FBUF_ADDR1,0x80000000);
1047        OUTREG32(PRI_STREAM2_FBUF_ADDR0,(pScrn->fbOffset & 0xfffffffc) | 0x80000000);
1048        OUTREG32(PRI_STREAM2_FBUF_ADDR1,pScrn->fbOffset & 0xffffffc);
1049    }
1050
1051    OUTREG32(0x8128, 0xFFFFFFFFL);
1052    OUTREG32(0x812C, 0xFFFFFFFFL);
1053
1054    if (!psav->IsSecondary)
1055    	/* bit 28:block write disable */
1056    	OUTREG32(S3_GLB_BD_HIGH, bci_enable | S3_BD64 | 0x10000000);
1057
1058    /* CR50, bit 7,6,0 = 111, Use GBD.*/
1059    OUTREG8(CRT_ADDRESS_REG,0x50);
1060    byte = INREG8(CRT_DATA_REG) | 0xC1;
1061    OUTREG8(CRT_DATA_REG, byte);
1062
1063    if (!psav->bTiled) {
1064        /*
1065         *  Do not enable block_write even for non-tiling modes, because
1066         *  the driver cannot determine if the memory type is the certain
1067         *  type of SGRAM for which block_write can be used.
1068         */
1069        psav->GlobalBD.bd1.HighPart.ResBWTile = TILE_FORMAT_LINEAR;/* linear */
1070
1071    }
1072    else if (pScrn->bitsPerPixel == 16) {
1073        psav->GlobalBD.bd1.HighPart.ResBWTile = tile16;/* tile format destination */
1074
1075        ulTmp =  (((pScrn->virtualX + 0x3f) & 0x0000ffc0) >> 6) << 20;
1076	if (psav->IsSecondary)
1077            OUTREG32(TILED_SURFACE_REGISTER_1,ulTmp | TILED_SURF_BPP16 | (pScrn->fbOffset>>6));
1078	else
1079            OUTREG32(TILED_SURFACE_REGISTER_0,ulTmp | TILED_SURF_BPP16 | (pScrn->fbOffset>>6));
1080    }
1081    else if (pScrn->bitsPerPixel == 32) {
1082        psav->GlobalBD.bd1.HighPart.ResBWTile = tile32;/* tile format destination */
1083
1084        ulTmp =  (((pScrn->virtualX + 0x1f) & 0x0000ffe0) >> 5) << 20;
1085	if (psav->IsSecondary)
1086            OUTREG32(TILED_SURFACE_REGISTER_1,ulTmp | TILED_SURF_BPP32 | (pScrn->fbOffset>>6));
1087	else
1088            OUTREG32(TILED_SURFACE_REGISTER_0,ulTmp | TILED_SURF_BPP32 | (pScrn->fbOffset>>6));
1089    }
1090
1091    psav->GlobalBD.bd1.HighPart.ResBWTile |= 0x10;/* disable block write */
1092    /* HW uses width */
1093    psav->GlobalBD.bd1.HighPart.Stride = (unsigned short)(psav->lDelta / (pScrn->bitsPerPixel >> 3));
1094    psav->GlobalBD.bd1.HighPart.Bpp = (unsigned char) (pScrn->bitsPerPixel);
1095    psav->GlobalBD.bd1.Offset = pScrn->fbOffset;
1096
1097    /*
1098     * CR31, bit 0 = 0, Disable address offset bits(CR6A_6-0).
1099     *       bit 0 = 1, Enable 8 Mbytes of display memory thru 64K window
1100     *                  at A000:0.
1101     */
1102    OUTREG8(CRT_ADDRESS_REG,MEMORY_CONFIG_REG);
1103    byte = INREG8(CRT_DATA_REG) & (~(ENABLE_CPUA_BASE_A0000));
1104    OUTREG8(CRT_DATA_REG,byte);
1105
1106    if (!psav->IsSecondary) {
1107    	/* program the GBD and SBDs */
1108    	OUTREG32(S3_GLB_BD_LOW,psav->GlobalBD.bd2.LoPart );
1109    	OUTREG32(S3_GLB_BD_HIGH,(psav->GlobalBD.bd2.HiPart
1110			     | bci_enable | S3_LITTLE_ENDIAN | S3_BD64));
1111    	OUTREG32(S3_PRI_BD_LOW,psav->GlobalBD.bd2.LoPart);
1112    	OUTREG32(S3_PRI_BD_HIGH,psav->GlobalBD.bd2.HiPart);
1113    	OUTREG32(S3_SEC_BD_LOW,psav->GlobalBD.bd2.LoPart);
1114    	OUTREG32(S3_SEC_BD_HIGH,psav->GlobalBD.bd2.HiPart);
1115    }
1116
1117    /* turn on screen */
1118    OUTREG8(SEQ_ADDRESS_REG,0x01);
1119    byte = INREG8(SEQ_DATA_REG) & ~0x20;
1120    OUTREG8(SEQ_DATA_REG,byte);
1121}
1122
1123void SavageSetGBD_2000(ScrnInfoPtr pScrn)
1124{
1125    SavagePtr psav = SAVPTR(pScrn);
1126    unsigned long ulTmp, ulYRange;
1127    unsigned char byte;
1128    int bci_enable, tile16, tile32;
1129
1130    bci_enable = BCI_ENABLE_TWISTER;
1131    tile16 = TILE_DESTINATION;
1132    tile32 = TILE_DESTINATION;
1133
1134    if (pScrn->virtualX > 1024)
1135      ulYRange = 0x40000000;
1136    else
1137      ulYRange = 0x20000000;
1138
1139
1140    /* following is the enable case */
1141
1142    /* SR01:turn off screen */
1143    OUTREG8 (SEQ_ADDRESS_REG,0x01);
1144    byte = INREG8(SEQ_DATA_REG) | 0x20;
1145    OUTREG8(SEQ_DATA_REG,byte);
1146
1147
1148    /* MM81C0 and 81B0 are used to control primary stream. */
1149    OUTREG32(PRI_STREAM_FBUF_ADDR0, pScrn->fbOffset);
1150    OUTREG32(PRI_STREAM2_FBUF_ADDR0, pScrn->fbOffset);
1151
1152
1153    /*
1154     *  Program Primary Stream Stride Register.
1155     *
1156     *  Tell engine if tiling on or off, set primary stream stride, and
1157     *  if tiling, set tiling bits/pixel and primary stream tile offset.
1158     *  Note that tile offset (bits 16 - 29) must be scanline width in
1159     *  bytes/128bytespertile * 256 Qwords/tile.  This is equivalent to
1160     *  lDelta * 2.  Remember that if tiling, lDelta is screenwidth in
1161     *  bytes padded up to an even number of tilewidths.
1162     */
1163    if (!psav->bTiled) {
1164        OUTREG32(PRI_STREAM_STRIDE,
1165		 ((psav->lDelta << 4) & 0x7ff0));
1166        OUTREG32(PRI_STREAM2_STRIDE,
1167                 ((psav->lDelta << 4) & 0x7ff0));
1168    } else {
1169        OUTREG32(PRI_STREAM_STRIDE,
1170		 (0x80000000 |((psav->lDelta << 4) & 0x7ff0)));
1171        OUTREG32(PRI_STREAM2_STRIDE,
1172                 (0x80000000 |((psav->lDelta << 4) & 0x7ff0)));
1173    }
1174
1175    /*
1176     * CR67_3:
1177     *  = 1  stream processor MMIO address and stride register
1178     *       are used to control the primary stream
1179     *  = 0  standard VGA address and stride registers
1180     *       are used to control the primary streams
1181     */
1182
1183    OUTREG8(CRT_ADDRESS_REG,0x67);
1184    byte =  INREG8(CRT_DATA_REG) | 0x08;
1185    OUTREG8(CRT_DATA_REG,byte);
1186
1187
1188    OUTREG32(0x8128, 0xFFFFFFFFL);
1189    OUTREG32(0x812C, 0xFFFFFFFFL);
1190
1191    /* bit 28:block write disable */
1192    OUTREG32(S3_GLB_BD_HIGH, bci_enable | S3_BD64 | 0x10000000);
1193
1194    /* CR50, bit 7,6,0 = 111, Use GBD.*/
1195    OUTREG8(CRT_ADDRESS_REG,0x50);
1196    byte = INREG8(CRT_DATA_REG) | 0xC1;
1197    OUTREG8(CRT_DATA_REG, byte);
1198
1199    /* CR73 bit 5 = 0 block write disable */
1200    OUTREG8(CRT_ADDRESS_REG,0x73);
1201    byte = INREG8(CRT_DATA_REG) & ~0x20;
1202    OUTREG8(CRT_DATA_REG, byte);
1203
1204    if (!psav->bTiled) {
1205        /*
1206         *  Do not enable block_write even for non-tiling modes, because
1207         *  the driver cannot determine if the memory type is the certain
1208         *  type of SGRAM for which block_write can be used.
1209         */
1210        psav->GlobalBD.bd1.HighPart.ResBWTile = TILE_FORMAT_LINEAR;/* linear */
1211
1212    }
1213    else if (pScrn->bitsPerPixel == 16) {
1214        psav->GlobalBD.bd1.HighPart.ResBWTile = tile16;/* tile format destination */
1215        ulTmp =  (((pScrn->virtualX + 0x3f) & 0x0000ffc0) >> 6) << 23;
1216        OUTREG32(TILED_SURFACE_REGISTER_0,ulTmp | TILED_SURF_BPP16_2000 | ulYRange);
1217        ulTmp |= (TILED_SURF_BPP16_2000 | ulYRange);
1218        OUTREG32(PRI_STREAM_STRIDE, ((ulTmp >> 19) & 0x03f0) | 0x80000000);
1219        OUTREG32(PRI_STREAM2_STRIDE, ((ulTmp >> 19) & 0x03f0) | 0x80000000);
1220    }
1221    else if (pScrn->bitsPerPixel == 32) {
1222        psav->GlobalBD.bd1.HighPart.ResBWTile = tile32;/* tile format destination */
1223        ulTmp =  (((pScrn->virtualX + 0x1f) & 0x0000ffe0) >> 5) << 23;
1224        OUTREG32(TILED_SURFACE_REGISTER_0,ulTmp | TILED_SURF_BPP32_2000 | ulYRange);
1225        ulTmp |= (TILED_SURF_BPP32_2000 | ulYRange);
1226        OUTREG32(PRI_STREAM_STRIDE, ((ulTmp >> 19) & 0x03f0) | 0x80000000);
1227        OUTREG32(PRI_STREAM2_STRIDE, ((ulTmp >> 19) & 0x03f0) | 0x80000000);
1228    }
1229
1230    psav->GlobalBD.bd1.HighPart.ResBWTile |= 0x10;/* disable block write */
1231    /* HW uses width */
1232    psav->GlobalBD.bd1.HighPart.Stride = (unsigned short)(psav->lDelta / (pScrn->bitsPerPixel >> 3));
1233    psav->GlobalBD.bd1.HighPart.Bpp = (unsigned char) (pScrn->bitsPerPixel);
1234    psav->GlobalBD.bd1.Offset = pScrn->fbOffset;
1235
1236    /*
1237     * CR31, bit 0 = 0, Disable address offset bits(CR6A_6-0).
1238     *       bit 0 = 1, Enable 8 Mbytes of display memory thru 64K window
1239     *                  at A000:0.
1240     */
1241    OUTREG8(CRT_ADDRESS_REG,MEMORY_CONFIG_REG);
1242    byte = INREG8(CRT_DATA_REG) & (~(ENABLE_CPUA_BASE_A0000));
1243    OUTREG8(CRT_DATA_REG,byte);
1244
1245    /* program the GBD and SBDs */
1246    OUTREG32(S3_GLB_BD_LOW,psav->GlobalBD.bd2.LoPart );
1247    OUTREG32(S3_GLB_BD_HIGH,(psav->GlobalBD.bd2.HiPart
1248			     | bci_enable | S3_LITTLE_ENDIAN | S3_BD64));
1249    OUTREG32(S3_PRI_BD_LOW,psav->GlobalBD.bd2.LoPart);
1250    OUTREG32(S3_PRI_BD_HIGH,psav->GlobalBD.bd2.HiPart);
1251    OUTREG32(S3_SEC_BD_LOW,psav->GlobalBD.bd2.LoPart);
1252    OUTREG32(S3_SEC_BD_HIGH,psav->GlobalBD.bd2.HiPart);
1253
1254    /* turn on screen */
1255    OUTREG8(SEQ_ADDRESS_REG,0x01);
1256    byte = INREG8(SEQ_DATA_REG) & ~0x20;
1257    OUTREG8(SEQ_DATA_REG,byte);
1258}
1259
1260#if 0
1261static
1262void SavageRestoreAccelState(ScrnInfoPtr pScrn)
1263{
1264    SavagePtr psav = SAVPTR(pScrn);
1265
1266    psav->WaitIdleEmpty(psav);
1267
1268    return;
1269}
1270#endif
1271
1272/* Acceleration init function, sets up pointers to our accelerated functions */
1273
1274Bool
1275SavageInitAccel(ScreenPtr pScreen)
1276{
1277    ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
1278    SavagePtr psav = SAVPTR(pScrn);
1279
1280#ifdef SAVAGEDRI
1281    if (psav->directRenderingEnabled) {
1282        SAVAGEDRIServerPrivatePtr pSAVAGEDRIServer = psav->DRIServerInfo;
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         *   turns out FALSE.
1459         * Now just reduce the level to 14.5MB, things should be OK, while the hwmc frame buffer layout
1460         *    calculation 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
1541int SavageGetCopyROP(int rop) {
1542
1543    int ALUCopyROP[16] =
1544    {
1545       0x00, /*ROP_0 GXclear */
1546       0x88, /*ROP_DSa GXand */
1547       0x44, /*ROP_SDna GXandReverse */
1548       0xCC, /*ROP_S GXcopy */
1549       0x22, /*ROP_DSna GXandInverted */
1550       0xAA, /*ROP_D GXnoop */
1551       0x66, /*ROP_DSx GXxor */
1552       0xEE, /*ROP_DSo GXor */
1553       0x11, /*ROP_DSon GXnor */
1554       0x99, /*ROP_DSxn GXequiv */
1555       0x55, /*ROP_Dn GXinvert*/
1556       0xDD, /*ROP_SDno GXorReverse */
1557       0x33, /*ROP_Sn GXcopyInverted */
1558       0xBB, /*ROP_DSno GXorInverted */
1559       0x77, /*ROP_DSan GXnand */
1560       0xFF, /*ROP_1 GXset */
1561    };
1562
1563    return (ALUCopyROP[rop]);
1564
1565}
1566
1567/* Routines for debugging. */
1568
1569
1570unsigned long
1571writedw( unsigned long addr, unsigned long value )
1572{
1573    SavagePtr psav = SAVPTR(gpScrn);
1574    OUTREG( addr, value );
1575    return INREG( addr );
1576}
1577
1578unsigned long
1579readdw( unsigned long addr )
1580{
1581    SavagePtr psav = SAVPTR(gpScrn);
1582    return INREG( addr );
1583}
1584
1585unsigned long
1586readfb( unsigned long addr )
1587{
1588    SavagePtr psav = SAVPTR(gpScrn);
1589    char * videobuffer = (char *) psav->FBBase;
1590    return *(volatile unsigned long*)(videobuffer + (addr & ~3) );
1591}
1592
1593unsigned long
1594writefb( unsigned long addr, unsigned long value )
1595{
1596    SavagePtr psav = SAVPTR(gpScrn);
1597    char * videobuffer = (char *) psav->FBBase;
1598    *(unsigned long*)(videobuffer + (addr & ~3)) = value;
1599    return *(volatile unsigned long*)(videobuffer + (addr & ~3) );
1600}
1601
1602void
1603writescan( unsigned long scan, unsigned long color )
1604{
1605    SavagePtr psav = SAVPTR(gpScrn);
1606    int i;
1607    char * videobuffer = (char *)psav->FBBase;
1608    videobuffer += scan * gpScrn->displayWidth * gpScrn->bitsPerPixel >> 3;
1609    for( i = gpScrn->displayWidth; --i; ) {
1610	switch( gpScrn->bitsPerPixel ) {
1611	    case 8:
1612		*videobuffer++ = color;
1613		break;
1614	    case 16:
1615		*(CARD16 *)videobuffer = color;
1616		videobuffer += 2;
1617		break;
1618	    case 32:
1619		*(CARD32 *)videobuffer = color;
1620		videobuffer += 4;
1621		break;
1622	}
1623    }
1624}
1625