~ubuntu-branches/ubuntu/precise/xserver-xorg-video-tdfx-lts-quantal/precise-proposed

« back to all changes in this revision

Viewing changes to src/tdfx_priv.c

  • Committer: Package Import Robot
  • Author(s): Maarten Lankhorst
  • Date: 2012-11-30 21:00:30 UTC
  • Revision ID: package-import@ubuntu.com-20121130210030-z6cpk5qrun266ihv
Tags: upstream-1.4.5
ImportĀ upstreamĀ versionĀ 1.4.5

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
 
2
#ifdef HAVE_CONFIG_H
 
3
#include "config.h"
 
4
#endif
 
5
 
 
6
#include <sys/time.h>
 
7
 
 
8
#include "xf86.h"
 
9
#include "xf86_OSproc.h"
 
10
#include "xf86fbman.h"
 
11
#include "compiler.h"
 
12
#include "tdfx.h"
 
13
 
 
14
/*
 
15
  Memory layout of card is as follows:
 
16
 
 
17
  000000-00ffff: VGA memory
 
18
  010000-013fff: Cursor 
 
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
 
23
   C    - D-1  : Back Buffer
 
24
   D    - E-1  : Depth Buffer
 
25
 
 
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.
 
30
*/
 
31
 
 
32
#if X_BYTE_ORDER == X_BIG_ENDIAN
 
33
void TDFXWriteFifo_24(TDFXPtr pTDFX, int val) {
 
34
  *pTDFX->fifoPtr++ = val;
 
35
}
 
36
 
 
37
void TDFXWriteFifo_16(TDFXPtr pTDFX, int val) {
 
38
  *pTDFX->fifoPtr++ = BE_WSWAP32(val);
 
39
}
 
40
 
 
41
void TDFXWriteFifo_8(TDFXPtr pTDFX, int val) {
 
42
  *pTDFX->fifoPtr++ = BE_BSWAP32(val);
 
43
}
 
44
#endif
 
45
 
 
46
 
 
47
static void TDFXSendNOPFifo3D(ScrnInfoPtr pScrn)
 
48
{
 
49
  TDFXPtr pTDFX;
 
50
 
 
51
  pTDFX=TDFXPTR(pScrn);
 
52
  TDFXAllocateSlots(pTDFX, 2);
 
53
  SET_3DPK4_HEADER(1, 0x48<<3);
 
54
  WRITE_FIFO(pTDFX, 0, 0);
 
55
}
 
56
 
 
57
void TDFXSendNOPFifo2D(ScrnInfoPtr pScrn)
 
58
{
 
59
  TDFXPtr pTDFX;
 
60
 
 
61
  pTDFX=TDFXPTR(pScrn);
 
62
  if (!pTDFX->syncDone) {
 
63
    TDFXFirstSync(pScrn);
 
64
    return;
 
65
  }
 
66
  TDFXAllocateSlots(pTDFX, 2);
 
67
  SET_PKT2_HEADER(SSTCP_COMMAND);
 
68
  WRITE_FIFO(pTDFX, SST_2D_COMMAND, SST_2D_NOP|SST_2D_GO);
 
69
}  
 
70
 
 
71
void TDFXSendNOPFifo(ScrnInfoPtr pScrn)
 
72
{
 
73
  TDFXSendNOPFifo2D(pScrn);
 
74
  TDFXSendNOPFifo3D(pScrn);
 
75
}
 
76
 
 
77
static void InstallFifo(ScrnInfoPtr pScrn)
 
78
{
 
79
  TDFXPtr pTDFX;
 
80
 
 
81
  pTDFX=TDFXPTR(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);
 
93
  else 
 
94
    TDFXWriteLongMMIO(pTDFX, SST_FIFO_FIFOTHRESH, (0xf<<5) | 0x8);
 
95
  TDFXWriteLongMMIO(pTDFX, SST_FIFO_BASESIZE0, ((pTDFX->fifoSize>>12)-1) | 
 
96
                    SST_EN_CMDFIFO);
 
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);
 
103
}
 
104
 
 
105
static void TDFXResetFifo(ScrnInfoPtr pScrn)
 
106
{
 
107
  TDFXPtr pTDFX;
 
108
  int oldValue;
 
109
  struct timeval start, stop;
 
110
 
 
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);
 
119
  do {
 
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);
 
126
  do {
 
127
    gettimeofday(&stop, NULL);
 
128
  } while (stop.tv_sec - start.tv_sec < 2);
 
129
  TDFXWriteLongMMIO(pTDFX, MISCINIT1, oldValue);
 
130
  InstallFifo(pScrn);
 
131
}
 
132
 
 
133
/*
 
134
  There are two steps to fully syncing the board:
 
135
  
 
136
  1) Send a NOP, which waits for any commands in progress
 
137
  2) Read the status register for 3 consecutive non-busy
 
138
 
 
139
  !!! We should use expedential backoff in our reads !!!
 
140
*/
 
141
static void TDFXSyncFifo(ScrnInfoPtr pScrn)
 
142
{
 
143
  TDFXPtr pTDFX;
 
144
  int i, cnt, resets=0;
 
145
  int stat;
 
146
  long tmp, readptr;
 
147
  struct timeval start, stop;
 
148
 
 
149
  TDFXTRACEACCEL("TDFXSyncFifo start\n");
 
150
  pTDFX=TDFXPTR(pScrn);
 
151
  TDFXSendNOPFifo(pScrn);
 
152
  i=0;
 
153
  cnt=0;
 
154
  start.tv_sec=0;
 
155
 
 
156
  readptr=TDFXReadLongMMIO(pTDFX, SST_FIFO_RDPTRL0);
 
157
  do {
 
158
    readptr=TDFXReadLongMMIO(pTDFX, SST_FIFO_RDPTRL0);
 
159
    stat=TDFXReadLongMMIO(pTDFX, 0);
 
160
    if (stat&SST_BUSY) i=0; else i++;
 
161
    cnt++;
 
162
    if (cnt==1000) {
 
163
      if (!start.tv_sec) {
 
164
        gettimeofday(&start, NULL);
 
165
      } else {
 
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);
 
171
            readptr = tmp;
 
172
            resets++;
 
173
            if (resets==3) {
 
174
              xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
 
175
                         "Board is not responding.\n");
 
176
              return;
 
177
            }
 
178
          }
 
179
          start.tv_sec=0;
 
180
        }
 
181
      }
 
182
      cnt=0;
 
183
    }
 
184
  } while (i<3);
 
185
  pTDFX->PciCnt=stat&0x1F;
 
186
  pTDFX->prevBlitDest.x1=pTDFX->prevBlitDest.y1=0;
 
187
  pTDFX->prevBlitDest.x2=pTDFX->prevBlitDest.y2=0;
 
188
}
 
189
 
 
190
Bool TDFXInitFifo(ScreenPtr pScreen)
 
191
{
 
192
  ScrnInfoPtr pScrn;
 
193
  TDFXPtr pTDFX;
 
194
 
 
195
  pScrn = xf86ScreenToScrn(pScreen);
 
196
  pTDFX=TDFXPTR(pScrn);
 
197
#ifdef DEBUG_FIFO
 
198
  pTDFX->fifoMirrorBase=0;
 
199
#endif
 
200
  pTDFX->fifoBase = (uint32*)(pTDFX->FbBase+pTDFX->fifoOffset);
 
201
#ifdef DEBUG_FIFO
 
202
  pTDFX->fifoMirrorBase = malloc(pTDFX->fifoSize);
 
203
  pTDFX->fifoMirrorPtr = pTDFX->fifoMirrorBase;
 
204
#endif
 
205
  pTDFX->sync=TDFXSyncFifo;
 
206
  InstallFifo(pScrn);
 
207
  return TRUE;
 
208
}
 
209
 
 
210
void TDFXShutdownFifo(ScreenPtr pScreen)
 
211
{
 
212
  ScrnInfoPtr pScrn;
 
213
  TDFXPtr pTDFX;
 
214
 
 
215
  pScrn = xf86ScreenToScrn(pScreen);
 
216
  pTDFX=TDFXPTR(pScrn);
 
217
  TDFXWriteLongMMIO(pTDFX, SST_FIFO_BASESIZE0, 0);
 
218
  pTDFX->sync=TDFXSync;
 
219
#ifdef DEBUG_FIFO
 
220
  if (pTDFX->fifoMirrorBase) free(pTDFX->fifoMirrorBase);
 
221
  pTDFX->fifoMirrorBase=0;
 
222
#endif
 
223
}
 
224
 
 
225
static uint32 
 
226
GetReadPtr(TDFXPtr pTDFX)
 
227
{
 
228
  uint32 read_ptr, dummy;
 
229
 
 
230
  do {
 
231
    dummy = TDFXReadLongMMIO(pTDFX, SST_FIFO_RDPTRL0);
 
232
    read_ptr = TDFXReadLongMMIO(pTDFX, SST_FIFO_RDPTRL0);
 
233
  } while (read_ptr != dummy);
 
234
  return read_ptr;
 
235
}
 
236
 
 
237
#ifdef TDFXDRI
 
238
void TDFXSwapContextFifo(ScreenPtr pScreen)
 
239
{
 
240
  ScrnInfoPtr pScrn;
 
241
  TDFXPtr pTDFX;
 
242
  int dummy, readPos;
 
243
  TDFXSAREAPriv *sPriv;
 
244
 
 
245
  pScrn = xf86ScreenToScrn(pScreen);
 
246
  pTDFX=TDFXPTR(pScrn);
 
247
  sPriv=(TDFXSAREAPriv*)DRIGetSAREAPrivate(pScreen);
 
248
  /* if (sPriv)
 
249
     ErrorF("In FifoPtr=%d FifoRead=%d\n", sPriv->fifoPtr, sPriv->fifoRead); */
 
250
#if 1
 
251
  do {
 
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;
 
258
#else
 
259
  sPriv=(TDFXSAREAPriv*)DRIGetSAREAPrivate(pScreen);
 
260
  if (!sPriv) return;
 
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");
 
266
    ResetFifo(pScrn);
 
267
  } else {
 
268
    pTDFX->fifoPtr = (unsigned int *)(pTDFX->FbBase+sPriv->fifoPtr);
 
269
    pTDFX->fifoRead = (unsigned int *)(pTDFX->FbBase+sPriv->fifoRead);
 
270
  }
 
271
#endif
 
272
  if (pTDFX->fifoRead>pTDFX->fifoPtr)
 
273
    pTDFX->fifoSlots = pTDFX->fifoRead-pTDFX->fifoPtr-1-8;
 
274
  else 
 
275
    pTDFX->fifoSlots = pTDFX->fifoEnd-pTDFX->fifoPtr-8;
 
276
}    
 
277
 
 
278
#endif
 
279
 
 
280
static void 
 
281
TDFXMakeSpace(TDFXPtr pTDFX, uint32 slots)
 
282
{
 
283
  uint32 slots_available;
 
284
 
 
285
  /*
 
286
  ** Check to see if we have to wrap to get enough space.
 
287
  */
 
288
  if (slots > pTDFX->fifoEnd-pTDFX->fifoPtr) {
 
289
    /*
 
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.
 
295
    **
 
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
 
298
    ** below.
 
299
    */
 
300
    do {
 
301
      pTDFX->fifoRead = (uint32*)(pTDFX->FbBase + GetReadPtr(pTDFX));
 
302
    }
 
303
    while (pTDFX->fifoRead>pTDFX->fifoPtr || 
 
304
           pTDFX->fifoRead == pTDFX->fifoBase);
 
305
    /*
 
306
    ** Put a jump command in command fifo to wrap to the beginning.
 
307
    */
 
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);
 
311
#else
 
312
    *pTDFX->fifoPtr = (pTDFX->fifoOffset >> 2) << SSTCP_PKT0_ADDR_SHIFT |
 
313
      SSTCP_PKT0_JMP_LOCAL;
 
314
#endif
 
315
    FLUSH_WCB();
 
316
 
 
317
    /*
 
318
    ** Reset the fifo_ptr to the beginning of the command fifo.
 
319
    */
 
320
    pTDFX->fifoPtr = pTDFX->fifoBase;
 
321
#ifdef DEBUG_FIFO
 
322
    pTDFX->fifoMirrorPtr = pTDFX->fifoMirrorBase;
 
323
#endif
 
324
  }
 
325
 
 
326
  /*
 
327
  ** Wait for enough slots to satisfy the request.
 
328
  */
 
329
  do {
 
330
    pTDFX->fifoRead = (uint32*)(pTDFX->FbBase + GetReadPtr(pTDFX));
 
331
 
 
332
    /*
 
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...
 
336
    **
 
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?
 
341
    */
 
342
    if ((uint32*)pTDFX->fifoRead > pTDFX->fifoPtr)
 
343
      slots_available = pTDFX->fifoRead - pTDFX->fifoPtr - 1;
 
344
    else
 
345
      slots_available = pTDFX->fifoEnd - pTDFX->fifoPtr;
 
346
  } while (slots > slots_available);
 
347
 
 
348
  pTDFX->fifoSlots = slots_available-slots;
 
349
}
 
350
 
 
351
void 
 
352
TDFXAllocateSlots(TDFXPtr pTDFX, int slots)
 
353
{
 
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");
 
359
  }
 
360
#endif
 
361
  pTDFX->fifoSlots-=slots;
 
362
  if (pTDFX->fifoSlots<0) TDFXMakeSpace(pTDFX, slots);
 
363
}