9
#include "xf86_OSproc.h"
10
#include "xf86fbman.h"
15
Memory layout of card is as follows:
17
000000-00ffff: VGA memory
19
011000-xxxxxx: Fifo (Min of CMDFIFO pages)
20
xxxxxx- A-1 : Front Buffer (framebuffer)
21
A - B-1 : Pixmap Cache (framebuffer)
22
B - C-1 : Texture Memory
24
D - E-1 : Depth Buffer
26
NB: pixmap cache usually butts right up against texture memory. when
27
3d is disabled (via Transition2D) then the pixmap cache is increased
28
to overlap the texture memory. maximum pixmap cache of 4095 lines on
29
voodoo5 and 2048 on voodoo3/4 applies.
32
#if X_BYTE_ORDER == X_BIG_ENDIAN
33
void TDFXWriteFifo_24(TDFXPtr pTDFX, int val) {
34
*pTDFX->fifoPtr++ = val;
37
void TDFXWriteFifo_16(TDFXPtr pTDFX, int val) {
38
*pTDFX->fifoPtr++ = BE_WSWAP32(val);
41
void TDFXWriteFifo_8(TDFXPtr pTDFX, int val) {
42
*pTDFX->fifoPtr++ = BE_BSWAP32(val);
47
static void TDFXSendNOPFifo3D(ScrnInfoPtr pScrn)
52
TDFXAllocateSlots(pTDFX, 2);
53
SET_3DPK4_HEADER(1, 0x48<<3);
54
WRITE_FIFO(pTDFX, 0, 0);
57
void TDFXSendNOPFifo2D(ScrnInfoPtr pScrn)
62
if (!pTDFX->syncDone) {
66
TDFXAllocateSlots(pTDFX, 2);
67
SET_PKT2_HEADER(SSTCP_COMMAND);
68
WRITE_FIFO(pTDFX, SST_2D_COMMAND, SST_2D_NOP|SST_2D_GO);
71
void TDFXSendNOPFifo(ScrnInfoPtr pScrn)
73
TDFXSendNOPFifo2D(pScrn);
74
TDFXSendNOPFifo3D(pScrn);
77
static void InstallFifo(ScrnInfoPtr pScrn)
82
/* Install the fifo */
83
TDFXWriteLongMMIO(pTDFX, SST_FIFO_BASEADDR0, pTDFX->fifoOffset>>12);
84
TDFXWriteLongMMIO(pTDFX, SST_FIFO_BUMP0, 0);
85
TDFXWriteLongMMIO(pTDFX, SST_FIFO_RDPTRL0, pTDFX->fifoOffset);
86
TDFXWriteLongMMIO(pTDFX, SST_FIFO_RDPTRH0, 0);
87
TDFXWriteLongMMIO(pTDFX, SST_FIFO_AMIN0, pTDFX->fifoOffset-4);
88
TDFXWriteLongMMIO(pTDFX, SST_FIFO_AMAX0, pTDFX->fifoOffset-4);
89
TDFXWriteLongMMIO(pTDFX, SST_FIFO_DEPTH0, 0);
90
TDFXWriteLongMMIO(pTDFX, SST_FIFO_HOLECNT0, 0);
91
if (pTDFX->ChipType == PCI_CHIP_BANSHEE)
92
TDFXWriteLongMMIO(pTDFX, SST_FIFO_FIFOTHRESH, (0x9<<5) | 0x2);
94
TDFXWriteLongMMIO(pTDFX, SST_FIFO_FIFOTHRESH, (0xf<<5) | 0x8);
95
TDFXWriteLongMMIO(pTDFX, SST_FIFO_BASESIZE0, ((pTDFX->fifoSize>>12)-1) |
97
/* Set the internal state */
98
pTDFX->fifoRead = pTDFX->fifoBase;
99
pTDFX->fifoPtr = pTDFX->fifoBase;
100
pTDFX->fifoSlots = (pTDFX->fifoSize>>2) - 1;
101
pTDFX->fifoEnd = pTDFX->fifoBase+pTDFX->fifoSlots;
102
TDFXSendNOPFifo(pScrn);
105
static void TDFXResetFifo(ScrnInfoPtr pScrn)
109
struct timeval start, stop;
111
pTDFX=TDFXPTR(pScrn);
112
ErrorF("Resetting FIFO\n");
113
/* Shut down the fifo */
114
TDFXWriteLongMMIO(pTDFX, SST_FIFO_BASESIZE0, 0);
115
/* Toggle the reset bits */
116
oldValue=TDFXReadLongMMIO(pTDFX, MISCINIT0);
117
TDFXWriteLongMMIO(pTDFX, MISCINIT0, oldValue|0x23);
118
gettimeofday(&start, NULL);
120
gettimeofday(&stop, NULL);
121
} while (stop.tv_sec - start.tv_sec < 2);
122
TDFXWriteLongMMIO(pTDFX, MISCINIT0, oldValue);
123
oldValue=TDFXReadLongMMIO(pTDFX, MISCINIT1);
124
TDFXWriteLongMMIO(pTDFX, MISCINIT1, oldValue|BIT(19));
125
gettimeofday(&start, NULL);
127
gettimeofday(&stop, NULL);
128
} while (stop.tv_sec - start.tv_sec < 2);
129
TDFXWriteLongMMIO(pTDFX, MISCINIT1, oldValue);
134
There are two steps to fully syncing the board:
136
1) Send a NOP, which waits for any commands in progress
137
2) Read the status register for 3 consecutive non-busy
139
!!! We should use expedential backoff in our reads !!!
141
static void TDFXSyncFifo(ScrnInfoPtr pScrn)
144
int i, cnt, resets=0;
147
struct timeval start, stop;
149
TDFXTRACEACCEL("TDFXSyncFifo start\n");
150
pTDFX=TDFXPTR(pScrn);
151
TDFXSendNOPFifo(pScrn);
156
readptr=TDFXReadLongMMIO(pTDFX, SST_FIFO_RDPTRL0);
158
readptr=TDFXReadLongMMIO(pTDFX, SST_FIFO_RDPTRL0);
159
stat=TDFXReadLongMMIO(pTDFX, 0);
160
if (stat&SST_BUSY) i=0; else i++;
164
gettimeofday(&start, NULL);
166
gettimeofday(&stop, NULL);
167
if (stop.tv_sec - start.tv_sec > 3) {
168
tmp = TDFXReadLongMMIO(pTDFX, SST_FIFO_RDPTRL0);
169
if (tmp == readptr) {
170
TDFXResetFifo(pScrn);
174
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
175
"Board is not responding.\n");
185
pTDFX->PciCnt=stat&0x1F;
186
pTDFX->prevBlitDest.x1=pTDFX->prevBlitDest.y1=0;
187
pTDFX->prevBlitDest.x2=pTDFX->prevBlitDest.y2=0;
190
Bool TDFXInitFifo(ScreenPtr pScreen)
195
pScrn = xf86ScreenToScrn(pScreen);
196
pTDFX=TDFXPTR(pScrn);
198
pTDFX->fifoMirrorBase=0;
200
pTDFX->fifoBase = (uint32*)(pTDFX->FbBase+pTDFX->fifoOffset);
202
pTDFX->fifoMirrorBase = malloc(pTDFX->fifoSize);
203
pTDFX->fifoMirrorPtr = pTDFX->fifoMirrorBase;
205
pTDFX->sync=TDFXSyncFifo;
210
void TDFXShutdownFifo(ScreenPtr pScreen)
215
pScrn = xf86ScreenToScrn(pScreen);
216
pTDFX=TDFXPTR(pScrn);
217
TDFXWriteLongMMIO(pTDFX, SST_FIFO_BASESIZE0, 0);
218
pTDFX->sync=TDFXSync;
220
if (pTDFX->fifoMirrorBase) free(pTDFX->fifoMirrorBase);
221
pTDFX->fifoMirrorBase=0;
226
GetReadPtr(TDFXPtr pTDFX)
228
uint32 read_ptr, dummy;
231
dummy = TDFXReadLongMMIO(pTDFX, SST_FIFO_RDPTRL0);
232
read_ptr = TDFXReadLongMMIO(pTDFX, SST_FIFO_RDPTRL0);
233
} while (read_ptr != dummy);
238
void TDFXSwapContextFifo(ScreenPtr pScreen)
243
TDFXSAREAPriv *sPriv;
245
pScrn = xf86ScreenToScrn(pScreen);
246
pTDFX=TDFXPTR(pScrn);
247
sPriv=(TDFXSAREAPriv*)DRIGetSAREAPrivate(pScreen);
249
ErrorF("In FifoPtr=%d FifoRead=%d\n", sPriv->fifoPtr, sPriv->fifoRead); */
252
dummy=TDFXReadLongMMIO(pTDFX, SST_FIFO_DEPTH0);
253
readPos=TDFXReadLongMMIO(pTDFX, SST_FIFO_DEPTH0);
254
} while (dummy || readPos);
255
readPos=(GetReadPtr(pTDFX)-pTDFX->fifoOffset)>>2;
256
pTDFX->fifoPtr = pTDFX->fifoBase+readPos;
257
pTDFX->fifoRead = pTDFX->fifoPtr;
259
sPriv=(TDFXSAREAPriv*)DRIGetSAREAPrivate(pScreen);
261
if ((sPriv->fifoPtr<pTDFX->fifoOffset) ||
262
(sPriv->fifoPtr>(int)pTDFX->fifoOffset+pTDFX->fifoSize) ||
263
(sPriv->fifoRead<pTDFX->fifoOffset) ||
264
(sPriv->fifoRead>(int)pTDFX->fifoOffset+pTDFX->fifoSize)) {
265
ErrorF("Invalid offsets passed between client and X server\n");
268
pTDFX->fifoPtr = (unsigned int *)(pTDFX->FbBase+sPriv->fifoPtr);
269
pTDFX->fifoRead = (unsigned int *)(pTDFX->FbBase+sPriv->fifoRead);
272
if (pTDFX->fifoRead>pTDFX->fifoPtr)
273
pTDFX->fifoSlots = pTDFX->fifoRead-pTDFX->fifoPtr-1-8;
275
pTDFX->fifoSlots = pTDFX->fifoEnd-pTDFX->fifoPtr-8;
281
TDFXMakeSpace(TDFXPtr pTDFX, uint32 slots)
283
uint32 slots_available;
286
** Check to see if we have to wrap to get enough space.
288
if (slots > pTDFX->fifoEnd-pTDFX->fifoPtr) {
290
** Make sure that the read pointer is not ahead of us in the
291
** the command fifo before wrapping.
292
** This insures two things:
293
** 1) There is room at fifo_ptr for the JMP packet.
294
** 2) There are slots available at the beginning of the fifo up to the read_ptr.
296
** Since we are wrapping, insure that the read pointer is not at the
297
** beginning of the fifo to prevent the ambiguous situation described
301
pTDFX->fifoRead = (uint32*)(pTDFX->FbBase + GetReadPtr(pTDFX));
303
while (pTDFX->fifoRead>pTDFX->fifoPtr ||
304
pTDFX->fifoRead == pTDFX->fifoBase);
306
** Put a jump command in command fifo to wrap to the beginning.
308
#if X_BYTE_ORDER == X_BIG_ENDIAN
309
WRITE_FIFO(pTDFX, 0, (pTDFX->fifoOffset >> 2) << SSTCP_PKT0_ADDR_SHIFT |
310
SSTCP_PKT0_JMP_LOCAL);
312
*pTDFX->fifoPtr = (pTDFX->fifoOffset >> 2) << SSTCP_PKT0_ADDR_SHIFT |
313
SSTCP_PKT0_JMP_LOCAL;
318
** Reset the fifo_ptr to the beginning of the command fifo.
320
pTDFX->fifoPtr = pTDFX->fifoBase;
322
pTDFX->fifoMirrorPtr = pTDFX->fifoMirrorBase;
327
** Wait for enough slots to satisfy the request.
330
pTDFX->fifoRead = (uint32*)(pTDFX->FbBase + GetReadPtr(pTDFX));
333
** If the HW read_ptr is ahead the SW fifo_ptr, we don't allocate the
334
** fifo slot immediately behind the HW read_ptr. This is to prevent
335
** the following ambiguous situation...
337
** If (HW read_ptr == SW fifo_ptr) is it because the HW read_ptr has
338
** caught up to the SW fifo_ptr and the fifo is completely empty
339
** OR is it because the SW fifo_ptr has caught up to the HW read_ptr
340
** and the fifo is completely full?
342
if ((uint32*)pTDFX->fifoRead > pTDFX->fifoPtr)
343
slots_available = pTDFX->fifoRead - pTDFX->fifoPtr - 1;
345
slots_available = pTDFX->fifoEnd - pTDFX->fifoPtr;
346
} while (slots > slots_available);
348
pTDFX->fifoSlots = slots_available-slots;
352
TDFXAllocateSlots(TDFXPtr pTDFX, int slots)
354
#ifdef TDFX_DEBUG_FIFO
355
if (pTDFX->fifoEnd-pTDFX->fifoPtr<pTDFX->fifoSlots)
356
ErrorF("FIFO overrun\n");
357
if (!pTDFX->syncDone) {
358
ErrorF("Writing to FIFO without sync\n");
361
pTDFX->fifoSlots-=slots;
362
if (pTDFX->fifoSlots<0) TDFXMakeSpace(pTDFX, slots);