1
/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/tdfx/tdfx_priv.c,v 1.16 2001/05/21 21:43:55 dawes Exp $ */
5
#include "xf86_OSproc.h"
6
#include "xf86_ansic.h"
12
Memory layout of card is as follows:
14
000000-00ffff: VGA memory
16
011000-xxxxxx: Fifo (Min of CMDFIFO pages)
17
xxxxxx- A-1 : Front Buffer (framebuffer)
18
A - B-1 : Pixmap Cache (framebuffer)
19
B - C-1 : Texture Memory
21
D - E-1 : Depth Buffer
23
NB: pixmap cache usually butts right up against texture memory. when
24
3d is disabled (via Transition2D) then the pixmap cache is increased
25
to overlap the texture memory. maximum pixmap cache of 4095 lines on
26
voodoo5 and 2048 on voodoo3/4 applies.
29
#if X_BYTE_ORDER == X_BIG_ENDIAN
30
void TDFXWriteFifo_24(TDFXPtr pTDFX, int val) {
31
*pTDFX->fifoPtr++ = val;
34
void TDFXWriteFifo_16(TDFXPtr pTDFX, int val) {
35
*pTDFX->fifoPtr++ = BE_WSWAP32(val);
38
void TDFXWriteFifo_8(TDFXPtr pTDFX, int val) {
39
*pTDFX->fifoPtr++ = BE_BSWAP32(val);
44
static void TDFXSendNOPFifo3D(ScrnInfoPtr pScrn)
49
TDFXAllocateSlots(pTDFX, 2);
50
SET_3DPK4_HEADER(1, 0x48<<3);
51
WRITE_FIFO(pTDFX, 0, 0);
54
void TDFXSendNOPFifo2D(ScrnInfoPtr pScrn)
59
if (!pTDFX->syncDone) {
63
TDFXAllocateSlots(pTDFX, 2);
64
SET_PKT2_HEADER(SSTCP_COMMAND);
65
WRITE_FIFO(pTDFX, SST_2D_COMMAND, SST_2D_NOP|SST_2D_GO);
68
void TDFXSendNOPFifo(ScrnInfoPtr pScrn)
70
TDFXSendNOPFifo2D(pScrn);
71
TDFXSendNOPFifo3D(pScrn);
74
static void InstallFifo(ScrnInfoPtr pScrn)
79
/* Install the fifo */
80
TDFXWriteLongMMIO(pTDFX, SST_FIFO_BASEADDR0, pTDFX->fifoOffset>>12);
81
TDFXWriteLongMMIO(pTDFX, SST_FIFO_BUMP0, 0);
82
TDFXWriteLongMMIO(pTDFX, SST_FIFO_RDPTRL0, pTDFX->fifoOffset);
83
TDFXWriteLongMMIO(pTDFX, SST_FIFO_RDPTRH0, 0);
84
TDFXWriteLongMMIO(pTDFX, SST_FIFO_AMIN0, pTDFX->fifoOffset-4);
85
TDFXWriteLongMMIO(pTDFX, SST_FIFO_AMAX0, pTDFX->fifoOffset-4);
86
TDFXWriteLongMMIO(pTDFX, SST_FIFO_DEPTH0, 0);
87
TDFXWriteLongMMIO(pTDFX, SST_FIFO_HOLECNT0, 0);
88
if (pTDFX->ChipType == PCI_CHIP_BANSHEE)
89
TDFXWriteLongMMIO(pTDFX, SST_FIFO_FIFOTHRESH, (0x9<<5) | 0x2);
91
TDFXWriteLongMMIO(pTDFX, SST_FIFO_FIFOTHRESH, (0xf<<5) | 0x8);
92
TDFXWriteLongMMIO(pTDFX, SST_FIFO_BASESIZE0, ((pTDFX->fifoSize>>12)-1) |
94
/* Set the internal state */
95
pTDFX->fifoRead = pTDFX->fifoBase;
96
pTDFX->fifoPtr = pTDFX->fifoBase;
97
pTDFX->fifoSlots = (pTDFX->fifoSize>>2) - 1;
98
pTDFX->fifoEnd = pTDFX->fifoBase+pTDFX->fifoSlots;
99
TDFXSendNOPFifo(pScrn);
102
static void TDFXResetFifo(ScrnInfoPtr pScrn)
106
long start_sec, end_sec, dummy;
108
pTDFX=TDFXPTR(pScrn);
109
ErrorF("Resetting FIFO\n");
110
/* Shut down the fifo */
111
TDFXWriteLongMMIO(pTDFX, SST_FIFO_BASESIZE0, 0);
112
/* Toggle the reset bits */
113
oldValue=TDFXReadLongMMIO(pTDFX, MISCINIT0);
114
TDFXWriteLongMMIO(pTDFX, MISCINIT0, oldValue|0x23);
115
getsecs(&start_sec, &dummy);
117
getsecs(&end_sec, &dummy);
118
} while (end_sec-start_sec<2);
119
TDFXWriteLongMMIO(pTDFX, MISCINIT0, oldValue);
120
oldValue=TDFXReadLongMMIO(pTDFX, MISCINIT1);
121
TDFXWriteLongMMIO(pTDFX, MISCINIT1, oldValue|BIT(19));
122
getsecs(&start_sec, &dummy);
124
getsecs(&end_sec, &dummy);
125
} while (end_sec-start_sec<2);
126
TDFXWriteLongMMIO(pTDFX, MISCINIT1, oldValue);
131
There are two steps to fully syncing the board:
133
1) Send a NOP, which waits for any commands in progress
134
2) Read the status register for 3 consecutive non-busy
136
!!! We should use expedential backoff in our reads !!!
138
static void TDFXSyncFifo(ScrnInfoPtr pScrn)
141
int i, cnt, resets=0;
143
long start_sec, end_sec, dummy, readptr;
145
TDFXTRACEACCEL("TDFXSyncFifo start\n");
146
pTDFX=TDFXPTR(pScrn);
147
TDFXSendNOPFifo(pScrn);
151
readptr=TDFXReadLongMMIO(pTDFX, SST_FIFO_RDPTRL0);
153
readptr=TDFXReadLongMMIO(pTDFX, SST_FIFO_RDPTRL0);
154
stat=TDFXReadLongMMIO(pTDFX, 0);
155
if (stat&SST_BUSY) i=0; else i++;
159
getsecs(&start_sec, &dummy);
161
getsecs(&end_sec, &dummy);
162
if (end_sec-start_sec>3) {
163
dummy=TDFXReadLongMMIO(pTDFX, SST_FIFO_RDPTRL0);
164
if (dummy==readptr) {
165
TDFXResetFifo(pScrn);
169
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
170
"Board is not responding.\n");
180
pTDFX->PciCnt=stat&0x1F;
181
pTDFX->prevBlitDest.x1=pTDFX->prevBlitDest.y1=0;
182
pTDFX->prevBlitDest.x2=pTDFX->prevBlitDest.y2=0;
185
Bool TDFXInitFifo(ScreenPtr pScreen)
190
pScrn = xf86Screens[pScreen->myNum];
191
pTDFX=TDFXPTR(pScrn);
193
pTDFX->fifoMirrorBase=0;
195
pTDFX->fifoBase = (uint32*)(pTDFX->FbBase+pTDFX->fifoOffset);
197
pTDFX->fifoMirrorBase = xalloc(pTDFX->fifoSize);
198
pTDFX->fifoMirrorPtr = pTDFX->fifoMirrorBase;
200
pTDFX->sync=TDFXSyncFifo;
205
void TDFXShutdownFifo(ScreenPtr pScreen)
210
pScrn = xf86Screens[pScreen->myNum];
211
pTDFX=TDFXPTR(pScrn);
212
TDFXWriteLongMMIO(pTDFX, SST_FIFO_BASESIZE0, 0);
213
pTDFX->sync=TDFXSync;
215
if (pTDFX->fifoMirrorBase) xfree(pTDFX->fifoMirrorBase);
216
pTDFX->fifoMirrorBase=0;
221
GetReadPtr(TDFXPtr pTDFX)
223
uint32 read_ptr, dummy;
226
dummy = TDFXReadLongMMIO(pTDFX, SST_FIFO_RDPTRL0);
227
read_ptr = TDFXReadLongMMIO(pTDFX, SST_FIFO_RDPTRL0);
228
} while (read_ptr != dummy);
233
void TDFXSwapContextFifo(ScreenPtr pScreen)
238
TDFXSAREAPriv *sPriv;
240
pScrn = xf86Screens[pScreen->myNum];
241
pTDFX=TDFXPTR(pScrn);
242
sPriv=(TDFXSAREAPriv*)DRIGetSAREAPrivate(pScreen);
244
ErrorF("In FifoPtr=%d FifoRead=%d\n", sPriv->fifoPtr, sPriv->fifoRead); */
247
dummy=TDFXReadLongMMIO(pTDFX, SST_FIFO_DEPTH0);
248
readPos=TDFXReadLongMMIO(pTDFX, SST_FIFO_DEPTH0);
249
} while (dummy || readPos);
250
readPos=(GetReadPtr(pTDFX)-pTDFX->fifoOffset)>>2;
251
pTDFX->fifoPtr = pTDFX->fifoBase+readPos;
252
pTDFX->fifoRead = pTDFX->fifoPtr;
254
sPriv=(TDFXSAREAPriv*)DRIGetSAREAPrivate(pScreen);
256
if ((sPriv->fifoPtr<pTDFX->fifoOffset) ||
257
(sPriv->fifoPtr>(int)pTDFX->fifoOffset+pTDFX->fifoSize) ||
258
(sPriv->fifoRead<pTDFX->fifoOffset) ||
259
(sPriv->fifoRead>(int)pTDFX->fifoOffset+pTDFX->fifoSize)) {
260
ErrorF("Invalid offsets passed between client and X server\n");
263
pTDFX->fifoPtr = (unsigned int *)(pTDFX->FbBase+sPriv->fifoPtr);
264
pTDFX->fifoRead = (unsigned int *)(pTDFX->FbBase+sPriv->fifoRead);
267
if (pTDFX->fifoRead>pTDFX->fifoPtr)
268
pTDFX->fifoSlots = pTDFX->fifoRead-pTDFX->fifoPtr-1-8;
270
pTDFX->fifoSlots = pTDFX->fifoEnd-pTDFX->fifoPtr-8;
276
TDFXMakeSpace(TDFXPtr pTDFX, uint32 slots)
278
uint32 slots_available;
281
** Check to see if we have to wrap to get enough space.
283
if (slots > pTDFX->fifoEnd-pTDFX->fifoPtr) {
285
** Make sure that the read pointer is not ahead of us in the
286
** the command fifo before wrapping.
287
** This insures two things:
288
** 1) There is room at fifo_ptr for the JMP packet.
289
** 2) There are slots available at the beginning of the fifo up to the read_ptr.
291
** Since we are wrapping, insure that the read pointer is not at the
292
** beginning of the fifo to prevent the ambiguous situation described
296
pTDFX->fifoRead = (uint32*)(pTDFX->FbBase + GetReadPtr(pTDFX));
298
while (pTDFX->fifoRead>pTDFX->fifoPtr ||
299
pTDFX->fifoRead == pTDFX->fifoBase);
301
** Put a jump command in command fifo to wrap to the beginning.
303
#if X_BYTE_ORDER == X_BIG_ENDIAN
304
WRITE_FIFO(pTDFX, 0, (pTDFX->fifoOffset >> 2) << SSTCP_PKT0_ADDR_SHIFT |
305
SSTCP_PKT0_JMP_LOCAL);
307
*pTDFX->fifoPtr = (pTDFX->fifoOffset >> 2) << SSTCP_PKT0_ADDR_SHIFT |
308
SSTCP_PKT0_JMP_LOCAL;
313
** Reset the fifo_ptr to the beginning of the command fifo.
315
pTDFX->fifoPtr = pTDFX->fifoBase;
317
pTDFX->fifoMirrorPtr = pTDFX->fifoMirrorBase;
322
** Wait for enough slots to satisfy the request.
325
pTDFX->fifoRead = (uint32*)(pTDFX->FbBase + GetReadPtr(pTDFX));
328
** If the HW read_ptr is ahead the SW fifo_ptr, we don't allocate the
329
** fifo slot immediately behind the HW read_ptr. This is to prevent
330
** the following ambiguous situation...
332
** If (HW read_ptr == SW fifo_ptr) is it because the HW read_ptr has
333
** caught up to the SW fifo_ptr and the fifo is completely empty
334
** OR is it because the SW fifo_ptr has caught up to the HW read_ptr
335
** and the fifo is completely full?
337
if ((uint32*)pTDFX->fifoRead > pTDFX->fifoPtr)
338
slots_available = pTDFX->fifoRead - pTDFX->fifoPtr - 1;
340
slots_available = pTDFX->fifoEnd - pTDFX->fifoPtr;
341
} while (slots > slots_available);
343
pTDFX->fifoSlots = slots_available-slots;
347
TDFXAllocateSlots(TDFXPtr pTDFX, int slots)
349
#ifdef TDFX_DEBUG_FIFO
350
if (pTDFX->fifoEnd-pTDFX->fifoPtr<pTDFX->fifoSlots)
351
ErrorF("FIFO overrun\n");
352
if (!pTDFX->syncDone) {
353
ErrorF("Writing to FIFO without sync\n");
356
pTDFX->fifoSlots-=slots;
357
if (pTDFX->fifoSlots<0) TDFXMakeSpace(pTDFX, slots);