source: trunk/src/opengl/glide/cvg/init/sli.c

Last change on this file was 6653, checked in by bird, 24 years ago

Added $Id:$ keyword.

File size: 29.0 KB
Line 
1/*-*-c++-*-*/
2/* $Id: sli.c,v 1.2 2001-09-05 14:30:42 bird Exp $ */
3/*
4** THIS SOFTWARE IS SUBJECT TO COPYRIGHT PROTECTION AND IS OFFERED ONLY
5** PURSUANT TO THE 3DFX GLIDE GENERAL PUBLIC LICENSE. THERE IS NO RIGHT
6** TO USE THE GLIDE TRADEMARK WITHOUT PRIOR WRITTEN PERMISSION OF 3DFX
7** INTERACTIVE, INC. A COPY OF THIS LICENSE MAY BE OBTAINED FROM THE
8** DISTRIBUTOR OR BY CONTACTING 3DFX INTERACTIVE INC(info@3dfx.com).
9** THIS PROGRAM IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
10** EXPRESSED OR IMPLIED. SEE THE 3DFX GLIDE GENERAL PUBLIC LICENSE FOR A
11** FULL TEXT OF THE NON-WARRANTY PROVISIONS.
12**
13** USE, DUPLICATION OR DISCLOSURE BY THE GOVERNMENT IS SUBJECT TO
14** RESTRICTIONS AS SET FORTH IN SUBDIVISION (C)(1)(II) OF THE RIGHTS IN
15** TECHNICAL DATA AND COMPUTER SOFTWARE CLAUSE AT DFARS 252.227-7013,
16** AND/OR IN SIMILAR OR SUCCESSOR CLAUSES IN THE FAR, DOD OR NASA FAR
17** SUPPLEMENT. UNPUBLISHED RIGHTS RESERVED UNDER THE COPYRIGHT LAWS OF
18** THE UNITED STATES.
19**
20** COPYRIGHT 3DFX INTERACTIVE, INC. 1999, ALL RIGHTS RESERVED
21**
22** $Revision: 1.2 $
23** $Date: 2001-09-05 14:30:42 $
24**
25** Initialization code for initializing scanline interleaving
26**
27*/
28#pragma optimize ("",off)
29#include <stdio.h>
30#include <stdlib.h>
31#include <math.h>
32#ifdef BUILD_FOR_SST1
33#include <sst.h>
34#else
35#include <3dfx.h>
36#include <cvgregs.h>
37#include <cvgdefs.h>
38#endif
39#define FX_DLL_DEFINITION
40#include <fxdll.h>
41#include <sst1vid.h>
42#include <sst1init.h>
43
44/*
45** sst1InitSli():
46** Setup Multiple SST-1 subsystems for Scanline Interleaving
47** sstbase0 defined to be the SLI Master
48** sstbase1 defined to be the SLI Slave
49**
50*/
51FX_EXPORT FxBool FX_CSTYLE sst1InitSli(FxU32 *sstbase0, FxU32 *sstbase1)
52{
53 FxU32 j, n, MasterPhysAddr, cntr;
54 SstRegs *sstMaster = (SstRegs *) sstbase0;
55 SstRegs *sstSlave = (SstRegs *) sstbase1;
56 FxU32 masterVInClkDel, masterVOutClkDel;
57 FxU32 slaveVInClkDel, slaveVOutClkDel;
58 FxU32 masterPVOutClkDel, slavePVOutClkDel;
59 FxU32 pciFifoLwm, memFifoLwm;
60 FxU32 memOffsetOrig, tilesInXOrig;
61 FxU32 memOffsetNew;
62 int memFifoEntriesNew;
63 FxU32 memSizeInPages;
64 FxU32 memFifoRowBaseNew;
65 FxU32 swapAlgorithm = SST_SWAP_SLISYNC;
66 FxU32 videoWindowActive = 0x1;
67 FxU32 videoWindowActiveDrag = 0xf;
68 sst1DeviceInfoStruct *sst1M, *sst1S;
69
70 if(sst1InitCheckBoard(sstbase1) == FXFALSE)
71 return(FXFALSE);
72 if(!sst1CurrentBoard->sliDetected)
73 return(FXFALSE);
74 sst1S = sst1CurrentBoard;
75
76 if(sst1InitCheckBoard(sstbase0) == FXFALSE)
77 return(FXFALSE);
78 if(!sst1CurrentBoard->sliDetected)
79 return(FXFALSE);
80 sst1M = sst1CurrentBoard;
81
82 // Verify that the board configurations are identical
83 //
84 // NB: Some of the tests are no longer necessary because
85 // the init code clients are doing the magic to make the
86 // board appear as the minimum value for things like memory.
87 if(/* (sst1M->fbiMemSize != sst1S->fbiMemSize) || */
88 /*(sst1M->tmuMemSize[0] != sst1S->tmuMemSize[0]) || */
89 (sst1M->numberTmus != sst1S->numberTmus) ||
90 (sst1M->fbiBoardID != sst1S->fbiBoardID) ||
91 /* (sst1M->fbiRevision != sst1S->fbiRevision) || */
92 /* (sst1M->tmuRevision != sst1S->tmuRevision) || */
93 (sst1M->fbiVideoStruct != sst1S->fbiVideoStruct)) {
94 INIT_PRINTF(("sst1InitSli() ERROR: Boards types must be identical...\n"));
95 return(FXFALSE);
96 }
97
98 // Verify that no video scanline doubling is being used...
99 if(sst1M->fbiVideoStruct->miscCtrl & BIT(1)) {
100 INIT_PRINTF(("sst1InitSli() ERROR: Scanline doubling not supported with SLI...\n"));
101 return(FXFALSE);
102 }
103
104 INIT_PRINTF(("sst1InitSli(): Enabling Scanline Interleaving...\n"));
105
106 // sst1Initidle() routines must be properly executed...
107 initIdleEnabled = 1;
108
109 // User override of swap algorithm...
110 if(GETENV(("SSTV2_SLISWAP"))) {
111 FxU32 swapAlg = ATOI(GETENV(("SSTV2_SLISWAP")));
112
113 if(swapAlg == 1) {
114 INIT_PRINTF(("sst1InitSli(): Using dac_data[0] for swapping(%d, %d)...\n", videoWindowActive, videoWindowActiveDrag));
115 swapAlgorithm = SST_SWAP_DACDATA0;
116 }
117 }
118
119 // Get values setup by sst1InitVideo()...
120 memOffsetOrig = (IGET(sstMaster->fbiInit2) & SST_VIDEO_BUFFER_OFFSET) >>
121 SST_VIDEO_BUFFER_OFFSET_SHIFT;
122 tilesInXOrig = (IGET(sstMaster->fbiInit1) & SST_VIDEO_TILES_IN_X) >>
123 SST_VIDEO_TILES_IN_X_SHIFT;
124 if(sstMaster->fbiInit1 & SST_VIDEO_TILES_IN_X_MSB)
125 tilesInXOrig += 16;
126
127 if(tilesInXOrig & 0x1) {
128 // (e.g. 800x600 resolution)
129 /*
130 Integer formula for:
131 memOffset =
132 (TRUNC((xDimension/64)+.99) *
133 TRUNC((((yDimension/2)+1)/32)+.99))
134 */
135 memOffsetNew = (tilesInXOrig *
136 ((((sst1CurrentBoard->fbiVideoHeight>>1)+1) + 31) >> 5));
137 } else {
138 // (e.g. 640x480 resolution)
139 // Calculate number of tiles in the vertical dimension
140 // Must add entire row of tiles at the bottom for fixes for
141 // Y-Origin at lower left
142 memOffsetNew = tilesInXOrig *
143 (((sst1CurrentBoard->fbiVideoHeight >> 1) + 32) >> 5);
144 }
145
146 if(sst1CurrentBoard->fbiMemSize == 1)
147 memSizeInPages = 256;
148 else if(sst1CurrentBoard->fbiMemSize == 2)
149 memSizeInPages = 512;
150 else
151 memSizeInPages = 1024;
152
153 memFifoRowBaseNew = (sst1CurrentBoard->fbiVideoColBuffs +
154 sst1CurrentBoard->fbiVideoAuxBuffs) * memOffsetNew;
155
156 memFifoEntriesNew = (65536 - (int)
157 (((int) (memSizeInPages - 1) -
158 (int) memFifoRowBaseNew) * 512)) >> 5;
159 if(memFifoEntriesNew <= 256)
160 memFifoEntriesNew = 0x100; // max. memory fifo size...
161 else if(memFifoEntriesNew >= 2048) {
162 INIT_PRINTF(("sst1InitSli(): Invalid memFifoEntriesNew 0x%x\n",
163 memFifoEntriesNew));
164 return(FXFALSE);
165 }
166
167 INIT_PRINTF(("sst1InitSli(): Allocating %d Color Buffers and %d Aux Buffer(s)...\n", sst1CurrentBoard->fbiVideoColBuffs, sst1CurrentBoard->fbiVideoAuxBuffs));
168 INIT_PRINTF(("sst1InitSli(): Allocating Memory/Command Fifo starting at page %d...\n", memFifoRowBaseNew));
169 INIT_PRINTF(("sst1InitSli(): Memory FIFO Entries: %d...\n",
170 65536 - (memFifoEntriesNew << 5)));
171#if 0
172 INIT_PRINTF(("sst1InitSli(): memOffsetOrig:%d, tilesInXOrig:%d\n",
173 memOffsetOrig, tilesInXOrig));
174 INIT_PRINTF(("sst1InitSli(): memOffsetNew:%d, memFifoEntriesNew:0x%x\n",
175 memOffsetNew, memFifoEntriesNew));
176#endif
177
178 // Setup SLI Slave...
179 cntr = 0;
180 while(1) {
181 if(sst1InitCheckBoard(sstbase1) == FXFALSE)
182 return(FXFALSE);
183 PCICFG_RD(SST1_PCI_INIT_ENABLE, j);
184 PCICFG_WR(SST1_PCI_INIT_ENABLE,
185 ((j & ~SST_SCANLINE_SLV_OWNPCI) | SST_SCANLINE_SLI_SLV));
186 ISET(sstSlave->fbiInit1, IGET(sstSlave->fbiInit1) |
187 (SST_VIDEO_RESET | SST_EN_SCANLINE_INTERLEAVE));
188 sst1InitIdleFBINoNOP(sstbase1);
189 ISET(SST_TREX(sstSlave,0)->trexInit1, sst1CurrentBoard->tmuInit1[0] |
190 SST_EN_TEX_SCANLINE_INTERLEAVE | SST_TEX_SCANLINE_INTERLEAVE_SLAVE);
191 sst1InitIdle(sstbase1);
192 ISET(SST_TREX(sstSlave,1)->trexInit1, sst1CurrentBoard->tmuInit1[1] |
193 SST_EN_TEX_SCANLINE_INTERLEAVE | SST_TEX_SCANLINE_INTERLEAVE_SLAVE);
194 sst1InitIdle(sstbase1);
195 ISET(SST_TREX(sstSlave,2)->trexInit1, sst1CurrentBoard->tmuInit1[2] |
196 SST_EN_TEX_SCANLINE_INTERLEAVE | SST_TEX_SCANLINE_INTERLEAVE_SLAVE);
197 sst1InitIdle(sstbase1);
198 sst1InitIdleFBINoNOP(sstbase1);
199 ISET(sstSlave->fbiInit2, (IGET(sstSlave->fbiInit2) &
200 ~SST_SWAP_ALGORITHM) | swapAlgorithm);
201 sst1InitIdleFBINoNOP(sstbase1);
202 // Initialize Y-Origin
203 ISET(sstSlave->fbiInit3, (IGET(sstSlave->fbiInit3) & ~SST_YORIGIN_TOP) |
204 (sst1CurrentBoard->fbiVideoHeight << SST_YORIGIN_TOP_SHIFT));
205 sst1InitIdleFBINoNOP(sstbase1);
206 ISET(sstSlave->fbiInit2, (IGET(sstSlave->fbiInit2) &
207 ~SST_VIDEO_BUFFER_OFFSET) |
208 (memOffsetNew << SST_VIDEO_BUFFER_OFFSET_SHIFT));
209 sst1CurrentBoard->fbiVideoMemOffset = memOffsetNew;
210 sst1InitIdleFBINoNOP(sstbase1);
211 // Initialize memory fifo
212 ISET(sstSlave->fbiInit0, (IGET(sstSlave->fbiInit0) &
213 ~SST_MEM_FIFO_HWM) | (memFifoEntriesNew << SST_MEM_FIFO_HWM_SHIFT));
214 sst1InitIdleFBINoNOP(sstbase1);
215 ISET(sstSlave->fbiInit4, (IGET(sstSlave->fbiInit4) &
216 ~SST_MEM_FIFO_ROW_BASE) |
217 (memFifoRowBaseNew << SST_MEM_FIFO_ROW_BASE_SHIFT));
218 sst1InitIdleFBINoNOP(sstbase1);
219 // Fix video dimensions
220 ISET(sstSlave->videoDimensions,
221 (((sst1CurrentBoard->fbiVideoHeight+2) << SST_VIDEO_YDIM_SHIFT) |
222 ((sst1CurrentBoard->fbiVideoWidth-1) << SST_VIDEO_XDIM_SHIFT)));
223 sst1InitIdleFBINoNOP(sstbase1);
224 // Setup video clocks
225 ISET(sstSlave->fbiInit5, (IGET(sstSlave->fbiInit5) &
226 ~(SST_VIDEO_CLK_SLAVE_OE_EN | SST_VID_CLK_2X_OUT_OE_EN)) |
227 SST_VID_CLK_DAC_DATA16_SEL);
228 ISET(sstSlave->fbiInit1, IGET(sstSlave->fbiInit1) &
229 ~SST_VIDEO_VID_CLK_SLAVE);
230 sst1CurrentBoard->fbiInit6 &= ~SST_SLI_SYNC_MASTER;
231 sst1CurrentBoard->fbiInit6 = ((sst1CurrentBoard->fbiInit6 &
232 ~(SST_SLI_SWAP_VACTIVE | SST_SLI_SWAP_VACTIVE_DRAG)) |
233 (videoWindowActive<<SST_SLI_SWAP_VACTIVE_SHIFT) |
234 (videoWindowActiveDrag<<SST_SLI_SWAP_VACTIVE_DRAG_SHIFT));
235 ISET(sstSlave->fbiInit6, sst1CurrentBoard->fbiInit6);
236
237 slaveVInClkDel = 0;
238 slaveVOutClkDel = 0;
239 slavePVOutClkDel = 0;
240
241 if(GETENV(("SSTV2_SLIS_VOUT_CLKDEL")))
242 SSCANF(GETENV(("SSTV2_SLIS_VOUT_CLKDEL")), "%i", &slaveVOutClkDel);
243 if(GETENV(("SSTV2_SLIS_PVOUT_CLKDEL")))
244 SSCANF(GETENV(("SSTV2_SLIS_PVOUT_CLKDEL")), "%i", &slavePVOutClkDel);
245 if(GETENV(("SSTV2_SLIS_VIN_CLKDEL")))
246 SSCANF(GETENV(("SSTV2_SLIS_VIN_CLKDEL")), "%i", &slaveVInClkDel);
247 INIT_PRINTF(("sst1InitSli(): slaveVinClkdel=0x%x, slaveVOutClkDel=0x%x, slavePVOutClkDel=0x%x\n",
248 slaveVInClkDel, slaveVOutClkDel, slavePVOutClkDel));
249 if(sst1CurrentBoard->fbiVideo16BPP)
250 // 16-bit Video Output
251 ISET(sstSlave->fbiInit1, (IGET(sstSlave->fbiInit1) &
252 ~(SST_VIDEO_VCLK_2X_OUTPUT_DEL | SST_VIDEO_VCLK_DEL |
253 SST_VIDEO_VCLK_SEL | SST_VIDEO_VCLK_2X_INPUT_DEL)) |
254 SST_EN_SCANLINE_INTERLEAVE |
255 // SST_VIDEO_VID_CLK_SLAVE |
256 // SST_VIDEO_VID_CLK_2X |
257 // SST_VIDEO_INVERT_VID_CLK_2X |
258 SST_VIDEO_VCLK_SEL |
259 SST_PCI_WRWS_1 |
260 (slaveVInClkDel << SST_VIDEO_VCLK_DEL_SHIFT) |
261 (slaveVOutClkDel << SST_VIDEO_VCLK_2X_OUTPUT_DEL_SHIFT) |
262 (slavePVOutClkDel << SST_VIDEO_VCLK_2X_INPUT_DEL_SHIFT));
263 else
264 // 24-bit Video Output
265 ISET(sstSlave->fbiInit1, (IGET(sstSlave->fbiInit1) &
266 ~(SST_VIDEO_VCLK_2X_OUTPUT_DEL | SST_VIDEO_VCLK_DEL |
267 SST_VIDEO_VCLK_SEL | SST_VIDEO_VCLK_2X_INPUT_DEL)) |
268 SST_EN_SCANLINE_INTERLEAVE |
269 // SST_VIDEO_VID_CLK_SLAVE |
270 // SST_VIDEO_VID_CLK_2X |
271 // SST_VIDEO_INVERT_VID_CLK_2X |
272 (0x0 << SST_VIDEO_VCLK_SEL_SHIFT) |
273 SST_PCI_WRWS_1 |
274 (slaveVInClkDel << SST_VIDEO_VCLK_DEL_SHIFT) |
275 (slaveVOutClkDel << SST_VIDEO_VCLK_2X_OUTPUT_DEL_SHIFT) |
276 (slavePVOutClkDel << SST_VIDEO_VCLK_2X_INPUT_DEL_SHIFT));
277 sst1InitIdleFBINoNOP(sstbase1);
278 ISET(sstSlave->fbiInit1, IGET(sstSlave->fbiInit1) &
279 ~(SST_VIDEO_DATA_OE_EN |
280 SST_VIDEO_BLANK_OE_EN |
281 SST_VIDEO_BLANK_EN |
282 SST_VIDEO_DCLK_OE_EN |
283 SST_VIDEO_HVSYNC_OE_EN));
284 sst1InitIdleFBINoNOP(sstbase1);
285 // Initialize pci and memory fifos...
286 pciFifoLwm = 16;
287 memFifoLwm = 26;
288 if(!GETENV(("SSTV2_PCIFIFO_LWM")))
289 ISET(sstSlave->fbiInit0, (IGET(sstSlave->fbiInit0) &
290 ~SST_PCI_FIFO_LWM) | (pciFifoLwm << SST_PCI_FIFO_LWM_SHIFT));
291 sst1InitIdleFBINoNOP(sstbase1);
292 if(!GETENV(("SSTV2_MEMFIFO_LWM")))
293 ISET(sstSlave->fbiInit4, (IGET(sstSlave->fbiInit4) &
294 ~SST_MEM_FIFO_LWM) | (memFifoLwm << SST_MEM_FIFO_LWM_SHIFT));
295 sst1InitIdleFBINoNOP(sstbase1);
296 INIT_PRINTF(("sst1InitSli(): Slave pciFifoLwm:%d, memFifoLwm:%d\n",
297 ((IGET(sstSlave->fbiInit0) & SST_PCI_FIFO_LWM) >>
298 SST_PCI_FIFO_LWM_SHIFT),
299 ((IGET(sstSlave->fbiInit4) & SST_MEM_FIFO_LWM) >>
300 SST_MEM_FIFO_LWM_SHIFT)));
301 sst1InitIdleFBINoNOP(sstbase1);
302 sst1InitIdleFBINoNOP(sstbase1);
303 ISET(sstSlave->fbiInit1, IGET(sstSlave->fbiInit1) |
304 (SST_EN_SCANLINE_INTERLEAVE | SST_VIDEO_RESET));
305 sst1InitIdleFBINoNOP(sstbase1);
306 sst1InitIdleFBINoNOP(sstbase1);
307 sst1InitIdleFBINoNOP(sstbase1);
308 ISET(sstSlave->fbiInit1, IGET(sstSlave->fbiInit1) & ~SST_VIDEO_RESET);
309 sst1InitIdleFBINoNOP(sstbase1);
310 sst1InitIdleFBINoNOP(sstbase1);
311 if(IGET(sstSlave->fbiInit1) & SST_VIDEO_RESET) {
312 INIT_PRINTF(("sst1InitSli(): Could not unReset Slave Video...\n"));
313 if(++cntr < 10)
314 continue;
315 else
316 return(FXFALSE);
317 }
318 if(!(IGET(sstSlave->fbiInit1) & SST_EN_SCANLINE_INTERLEAVE)) {
319 INIT_PRINTF(("sst1InitSli(): Could not setup SLI Slave...\n"));
320 if(++cntr < 10)
321 continue;
322 else
323 return(FXFALSE);
324 }
325 break;
326 }
327
328 // Setup SLI Master...
329 if(sst1InitCheckBoard(sstbase0) == FXFALSE)
330 return(FXFALSE);
331 ISET(sstMaster->fbiInit1, IGET(sstMaster->fbiInit1) | SST_VIDEO_RESET);
332 ISET(SST_TREX(sstMaster,0)->trexInit1, sst1CurrentBoard->tmuInit1[0] |
333 SST_EN_TEX_SCANLINE_INTERLEAVE);
334 sst1InitIdle(sstbase0);
335 ISET(SST_TREX(sstMaster,1)->trexInit1, sst1CurrentBoard->tmuInit1[1] |
336 SST_EN_TEX_SCANLINE_INTERLEAVE);
337 sst1InitIdle(sstbase0);
338 ISET(SST_TREX(sstMaster,2)->trexInit1, sst1CurrentBoard->tmuInit1[2] |
339 SST_EN_TEX_SCANLINE_INTERLEAVE);
340 sst1InitIdle(sstbase0);
341 sst1InitIdleFBINoNOP(sstbase0);
342 ISET(sstMaster->fbiInit2, (IGET(sstMaster->fbiInit2) &
343 ~SST_SWAP_ALGORITHM) | swapAlgorithm);
344 sst1InitIdleFBINoNOP(sstbase0);
345 // Initialize Y-Origin
346 ISET(sstMaster->fbiInit3, (IGET(sstMaster->fbiInit3) & ~SST_YORIGIN_TOP) |
347 ((sst1CurrentBoard->fbiVideoHeight) << SST_YORIGIN_TOP_SHIFT));
348 sst1InitIdleFBINoNOP(sstbase0);
349 if(sst1CurrentBoard->fbiVideoWidth == 960)
350 ISET(sstMaster->fbiInit0, IGET(sstMaster->fbiInit0) & ~SST_MEM_FIFO_EN);
351 ISET(sstMaster->fbiInit2, (IGET(sstMaster->fbiInit2) &
352 ~SST_VIDEO_BUFFER_OFFSET) |
353 (memOffsetNew << SST_VIDEO_BUFFER_OFFSET_SHIFT));
354 sst1CurrentBoard->fbiVideoMemOffset = memOffsetNew;
355 sst1InitIdleFBINoNOP(sstbase0);
356 // // Initialize memory fifo
357 ISET(sstMaster->fbiInit0, (IGET(sstMaster->fbiInit0) & ~SST_MEM_FIFO_HWM) |
358 (memFifoEntriesNew << SST_MEM_FIFO_HWM_SHIFT));
359 sst1InitIdleFBINoNOP(sstbase0);
360 ISET(sstMaster->fbiInit4, (IGET(sstMaster->fbiInit4) &
361 ~SST_MEM_FIFO_ROW_BASE) |
362 (memFifoRowBaseNew << SST_MEM_FIFO_ROW_BASE_SHIFT));
363 sst1InitIdleFBINoNOP(sstbase0);
364 // Fix video dimensions
365 ISET(sstMaster->videoDimensions,
366 (((sst1CurrentBoard->fbiVideoHeight+2) << SST_VIDEO_YDIM_SHIFT) |
367 ((sst1CurrentBoard->fbiVideoWidth-1) << SST_VIDEO_XDIM_SHIFT)));
368 sst1InitIdleFBINoNOP(sstbase0);
369 // Setup video clocks
370 ISET(sstMaster->fbiInit5, IGET(sstMaster->fbiInit5) |
371 SST_VIDEO_CLK_SLAVE_OE_EN | SST_VID_CLK_2X_OUT_OE_EN |
372 SST_VID_CLK_DAC_DATA16_SEL);
373 ISET(sstMaster->fbiInit1, IGET(sstMaster->fbiInit1) &
374 ~SST_VIDEO_VID_CLK_SLAVE);
375 sst1CurrentBoard->fbiInit6 |= SST_SLI_SYNC_MASTER;
376 sst1CurrentBoard->fbiInit6 = ((sst1CurrentBoard->fbiInit6 &
377 ~(SST_SLI_SWAP_VACTIVE | SST_SLI_SWAP_VACTIVE_DRAG)) |
378 (videoWindowActive<<SST_SLI_SWAP_VACTIVE_SHIFT) |
379 (videoWindowActiveDrag<<SST_SLI_SWAP_VACTIVE_DRAG_SHIFT));
380 ISET(sstMaster->fbiInit6, sst1CurrentBoard->fbiInit6);
381
382 // Following work well up to around 100 MHz...
383 // masterVInClkDel = 2;
384 // masterVOutClkDel = 0;
385 // masterPVOutClkDel = 0;
386 // Following seem to work up to 800x600@85 Hz (112 MHz)
387 masterVInClkDel = 3;
388 masterVOutClkDel = 2;
389 masterPVOutClkDel = 0;
390 if(GETENV(("SSTV2_SLIM_VOUT_CLKDEL")))
391 SSCANF(GETENV(("SSTV2_SLIM_VOUT_CLKDEL")), "%i", &masterVOutClkDel);
392 if(GETENV(("SSTV2_SLIM_PVOUT_CLKDEL")))
393 SSCANF(GETENV(("SSTV2_SLIM_PVOUT_CLKDEL")), "%i", &masterPVOutClkDel);
394 if(GETENV(("SSTV2_SLIM_VIN_CLKDEL")))
395 SSCANF(GETENV(("SSTV2_SLIM_VIN_CLKDEL")), "%i", &masterVInClkDel);
396 INIT_PRINTF(("sst1InitSli(): masterVinClkdel=0x%x, masterVOutClkDel=0x%x, masterPVOutClkDel=0x%x\n",
397 masterVInClkDel, masterVOutClkDel, masterPVOutClkDel));
398 if(sst1CurrentBoard->fbiVideo16BPP)
399 // 16-bit Video Output
400 ISET(sstMaster->fbiInit1, (IGET(sstMaster->fbiInit1) &
401 ~(SST_VIDEO_VCLK_2X_OUTPUT_DEL | SST_VIDEO_VCLK_DEL |
402 SST_VIDEO_VCLK_SEL | SST_VIDEO_VCLK_2X_INPUT_DEL |
403 SST_VIDEO_BLANK_EN)) |
404 SST_EN_SCANLINE_INTERLEAVE |
405 // SST_VIDEO_VID_CLK_2X |
406 // SST_VIDEO_INVERT_VID_CLK_2X |
407 SST_VIDEO_VCLK_SEL |
408 SST_PCI_WRWS_1 |
409 SST_VIDEO_DATA_OE_EN |
410 SST_VIDEO_DCLK_OE_EN |
411 SST_VIDEO_HVSYNC_OE_EN |
412 (masterVInClkDel << SST_VIDEO_VCLK_DEL_SHIFT) |
413 (masterVOutClkDel << SST_VIDEO_VCLK_2X_OUTPUT_DEL_SHIFT) |
414 (masterPVOutClkDel << SST_VIDEO_VCLK_2X_INPUT_DEL_SHIFT));
415 else {
416 // 24-bit Video Output
417 ISET(sstMaster->fbiInit1, (IGET(sstMaster->fbiInit1) &
418 ~(SST_VIDEO_VCLK_2X_OUTPUT_DEL | SST_VIDEO_VCLK_DEL |
419 SST_VIDEO_VCLK_SEL | SST_VIDEO_VCLK_2X_INPUT_DEL |
420 SST_VIDEO_BLANK_EN)) |
421 SST_EN_SCANLINE_INTERLEAVE |
422 // SST_VIDEO_VID_CLK_2X |
423 // SST_VIDEO_INVERT_VID_CLK_2X |
424 (0x0 << SST_VIDEO_VCLK_SEL_SHIFT) |
425 SST_PCI_WRWS_1 |
426 SST_VIDEO_DATA_OE_EN |
427 SST_VIDEO_DCLK_OE_EN |
428 SST_VIDEO_HVSYNC_OE_EN |
429 (masterVInClkDel << SST_VIDEO_VCLK_DEL_SHIFT) |
430 (masterVOutClkDel << SST_VIDEO_VCLK_2X_OUTPUT_DEL_SHIFT) |
431 (masterPVOutClkDel << SST_VIDEO_VCLK_2X_INPUT_DEL_SHIFT));
432 sst1InitReturnStatus(sstbase0);
433 ISET(sstMaster->fbiInit5, IGET(sstMaster->fbiInit5) |
434 SST_VIDEO_CLK_SLAVE_OE_EN | SST_VID_CLK_2X_OUT_OE_EN);
435 }
436 sst1InitIdleFBINoNOP(sstbase0);
437 // Initialize pci and memory fifos...
438 pciFifoLwm = 16;
439 memFifoLwm = 26;
440 if(!GETENV(("SSTV2_PCIFIFO_LWM")))
441 ISET(sstMaster->fbiInit0, (IGET(sstMaster->fbiInit0) &
442 ~SST_PCI_FIFO_LWM) | (pciFifoLwm << SST_PCI_FIFO_LWM_SHIFT));
443 sst1InitIdleFBINoNOP(sstbase0);
444 if(!GETENV(("SSTV2_MEMFIFO_LWM")))
445 ISET(sstMaster->fbiInit4, (IGET(sstMaster->fbiInit4) &
446 ~SST_MEM_FIFO_LWM) | (memFifoLwm << SST_MEM_FIFO_LWM_SHIFT));
447 sst1InitIdleFBINoNOP(sstbase0);
448 INIT_PRINTF(("sst1InitSli(): Master pciFifoLwm:%d, memFifoLwm:%d\n",
449 ((IGET(sstMaster->fbiInit0) & SST_PCI_FIFO_LWM) >>
450 SST_PCI_FIFO_LWM_SHIFT),
451 ((IGET(sstMaster->fbiInit4) & SST_MEM_FIFO_LWM) >>
452 SST_MEM_FIFO_LWM_SHIFT)));
453 ISET(sstMaster->fbiInit1, IGET(sstMaster->fbiInit1) & ~SST_VIDEO_RESET);
454 sst1InitIdleFBINoNOP(sstbase0);
455
456 // Master
457 if(sst1InitCheckBoard(sstbase0) == FXFALSE)
458 return(FXFALSE);
459 PCICFG_RD(SST1_PCI_INIT_ENABLE, j);
460 PCICFG_WR(SST1_PCI_INIT_ENABLE,
461 (j & ~(SST_SCANLINE_SLV_OWNPCI | SST_SCANLINE_SLI_SLV)));
462 MasterPhysAddr = sst1CurrentBoard->physAddr[0];
463 sst1InitReturnStatus(sstbase0); // flush pci packer with reads
464 sst1InitReturnStatus(sstbase0);
465 sst1InitReturnStatus(sstbase0);
466
467 // Slave
468 if(sst1InitCheckBoard(sstbase1) == FXFALSE)
469 return(FXFALSE);
470 PCICFG_RD(SST1_PCI_INIT_ENABLE, j);
471 PCICFG_WR(SST1_PCI_INIT_ENABLE,
472 ((j & ~(SST_SCANLINE_SLV_OWNPCI)) | SST_SCANLINE_SLI_SLV));
473
474 /* dpc - 19 may 1998 - FixMe
475 * Min the clock values for the two boards so that they are
476 * happy running together.
477 */
478#define MIN(__a, __b) (((__a) < (__b)) ? (__a) : (__b))
479 {
480 sst1DeviceInfoStruct* infoMaster;
481 sst1DeviceInfoStruct* infoSlave;
482
483 if (!sst1InitCheckBoard(sstbase0)) return FXFALSE;
484 infoMaster = sst1CurrentBoard;
485
486 if (!sst1InitCheckBoard(sstbase1)) return FXFALSE;
487 infoSlave = sst1CurrentBoard;
488
489 /* fbi and tmu clock freqs should be equal since they are
490 * both set from sst1InitCalcGrxClk.
491 */
492 if (infoMaster->fbiGrxClkFreq != infoSlave->fbiGrxClkFreq) {
493 /* Recompute the actual clock rates before any clocking down
494 * due to sli for some board revisions.
495 */
496 if (!sst1InitCalcGrxClk(sstbase0)) return FXFALSE;
497 if (!sst1InitCalcGrxClk(sstbase1)) return FXFALSE;
498
499 /* Save the min clock of the two boards */
500 infoMaster->fbiGrxClkFreq =
501 infoMaster->tmuGrxClkFreq =
502 infoSlave->fbiGrxClkFreq =
503 infoSlave->tmuGrxClkFreq = MIN(infoMaster->fbiGrxClkFreq, infoSlave->fbiGrxClkFreq);
504
505 /* Clear the clock setting bits */
506 infoMaster->initGrxClkDone =
507 infoSlave->initGrxClkDone = FXFALSE;
508
509 /* Reset the clocks for each board */
510 if (!sst1InitGrxClk(sstbase0)) return FXFALSE;
511 if (!sst1InitGrxClk(sstbase1)) return FXFALSE;
512
513 /* Now check for the memory configurations of the devices.
514 * They no longer need to match, but any future calls to
515 * sst1InitGetDeviceInfo should now reflect the current
516 * minimized state of the world.
517 */
518 {
519 FxU32 memSize, i;
520
521 if (infoMaster->fbiMemSize != infoSlave->fbiMemSize) {
522 memSize = MIN(infoMaster->fbiMemSize, infoSlave->fbiMemSize);
523 infoMaster->fbiMemSize =
524 infoSlave->fbiMemSize = memSize;
525 }
526
527 for(i = 0; i < infoMaster->numberTmus; i++) {
528 if (infoMaster->tmuMemSize[i] != infoSlave->tmuMemSize[i]) {
529 memSize = MIN(infoMaster->tmuMemSize[i], infoSlave->tmuMemSize[i]);
530 infoMaster->tmuMemSize[i] =
531 infoSlave->tmuMemSize[i] = memSize;
532 }
533 }
534 }
535 }
536 }
537#undef MIN
538
539 // Enable SLI Bus Snooping for the Slave
540 PCICFG_RD(SST1_PCI_INIT_ENABLE, j);
541 PCICFG_WR(SST1_PCI_INIT_ENABLE, (j & ~SST_SLI_SNOOP_MEMBASE) |
542 ((MasterPhysAddr>>24 & 0xff) << SST_SLI_SNOOP_MEMBASE_SHIFT));
543 PCICFG_RD(SST1_PCI_INIT_ENABLE, j);
544 PCICFG_WR(SST1_PCI_INIT_ENABLE, j | SST_SLI_SNOOP_EN);
545 sst1InitReturnStatus(sstbase1); // flush pci packer with reads
546 sst1InitReturnStatus(sstbase1);
547 sst1InitReturnStatus(sstbase1);
548
549 // Reset video unit in both Master and Slave
550 // Then, reset graphics unit in both Master and Slave
551 // Finally, deassert both resets to guarantee that Master and Slave
552 // see the same vsyncs (and maintain the same swap buffer counter)
553
554 // Probit writes to PCI fifo while resetting graphics core
555 if(sst1InitCheckBoard(sstbase0) == FXFALSE)
556 return(FXFALSE);
557 PCICFG_RD(SST1_PCI_INIT_ENABLE, j);
558 PCICFG_WR(SST1_PCI_INIT_ENABLE, j & ~SST_PCI_FIFOWR_EN);
559 if(sst1InitCheckBoard(sstbase1) == FXFALSE)
560 return(FXFALSE);
561 PCICFG_RD(SST1_PCI_INIT_ENABLE, j);
562 PCICFG_WR(SST1_PCI_INIT_ENABLE, j & ~SST_PCI_FIFOWR_EN);
563
564 // Reset Video core...
565 if(sst1InitCheckBoard(sstbase0) == FXFALSE)
566 return(FXFALSE);
567 ISET(sstMaster->fbiInit1, IGET(sstMaster->fbiInit1) | SST_VIDEO_RESET);
568 sst1InitReturnStatus(sstbase0);
569 ISET(sstSlave->fbiInit1, IGET(sstSlave->fbiInit1) | SST_VIDEO_RESET);
570 sst1InitReturnStatus(sstbase1);
571
572 // Reset Graphics core...
573 ISET(sstMaster->fbiInit0, IGET(sstMaster->fbiInit0) | SST_GRX_RESET);
574 sst1InitReturnStatus(sstbase0);
575 ISET(sstSlave->fbiInit0, IGET(sstSlave->fbiInit0) | SST_GRX_RESET);
576 sst1InitReturnStatus(sstbase1);
577
578 // Allow resets to propogate...
579 sst1InitReturnStatus(sstbase0);
580 sst1InitReturnStatus(sstbase1);
581 sst1InitReturnStatus(sstbase0);
582 sst1InitReturnStatus(sstbase1);
583
584 // De-assert reset to Graphics core...
585 ISET(sstMaster->fbiInit0, IGET(sstMaster->fbiInit0) & ~SST_GRX_RESET);
586 sst1InitReturnStatus(sstbase0);
587 ISET(sstSlave->fbiInit0, IGET(sstSlave->fbiInit0) & ~SST_GRX_RESET);
588 sst1InitReturnStatus(sstbase1);
589
590 // De-assert reset to Video core...
591 ISET(sstMaster->fbiInit1, IGET(sstMaster->fbiInit1) & ~SST_VIDEO_RESET);
592 sst1InitReturnStatus(sstbase0);
593 ISET(sstSlave->fbiInit1, IGET(sstSlave->fbiInit1) & ~SST_VIDEO_RESET);
594 sst1InitReturnStatus(sstbase1);
595
596 // Allow writes to PCI fifo...
597 if(sst1InitCheckBoard(sstbase0) == FXFALSE)
598 return(FXFALSE);
599 PCICFG_RD(SST1_PCI_INIT_ENABLE, j);
600 PCICFG_WR(SST1_PCI_INIT_ENABLE, j | SST_PCI_FIFOWR_EN);
601 // Update info structure for initEnable
602 sst1CurrentBoard->fbiInitEnable = j | SST_PCI_FIFOWR_EN;
603
604 if(sst1InitCheckBoard(sstbase1) == FXFALSE)
605 return(FXFALSE);
606 PCICFG_RD(SST1_PCI_INIT_ENABLE, j);
607 PCICFG_WR(SST1_PCI_INIT_ENABLE, j | SST_PCI_FIFOWR_EN);
608 // Update info structure for initEnable
609 sst1CurrentBoard->fbiInitEnable = j | SST_PCI_FIFOWR_EN;
610
611 if(sst1InitCheckBoard(sstbase0) == FXFALSE)
612 return(FXFALSE);
613
614 // Clear fbistat registers after clearing screen
615 ISET(sstMaster->nopCMD, 0x1);
616
617 sst1CurrentBoard->sliSlaveVirtAddr = sstbase1;
618
619 sst1InitIdle(sstbase0);
620
621 // Synchronize Boards
622 for(j=0; j<3; j++) {
623 while(!(sst1InitReturnStatus(sstbase0) & SST_VRETRACE))
624 ;
625 IGET(sstMaster->status);
626 ISET(sstMaster->swapbufferCMD, 0x0); // Do not wait for vRetrace...
627 IGET(sstMaster->status);
628 sst1InitIdle(sstbase0);
629 }
630 while(!(sst1InitReturnStatus(sstbase0) & SST_VRETRACE))
631 ;
632 IGET(sstMaster->status);
633 ISET(sstMaster->swapbufferCMD, 0x1); // Sync to vRetrace...
634 IGET(sstMaster->status);
635 sst1InitIdle(sstbase0);
636
637 if(GETENV(("SSTV2_IGNORE_IDLE")))
638 initIdleEnabled = 0;
639
640 INIT_PRINTF(("sst1InitSli() exiting with status %d...\n", FXTRUE));
641 return(FXTRUE);
642}
643
644/*
645** sst1InitShutdownSli():
646** Shutdown SLI configuration
647**
648*/
649FX_EXPORT FxBool FX_CSTYLE sst1InitShutdownSli(FxU32 *sstbase)
650{
651 SstRegs *sstMaster = (SstRegs *) sstbase;
652 SstRegs *sstSlave;
653 FxU32 n, j, cntr;
654
655 if(sst1InitCheckBoard(sstbase) == FXFALSE)
656 return(FXFALSE);
657
658 sstSlave = (SstRegs *) sst1CurrentBoard->sliSlaveVirtAddr;
659
660 if(sst1CurrentBoard->sliSlaveVirtAddr != (FxU32 *) NULL) {
661 INIT_PRINTF(("sst1InitShutdownSli(): Disabling Scanline Interleaving...\n"));
662 sst1CurrentBoard->sliSlaveVirtAddr = (FxU32 *) NULL;
663
664 cntr = 0;
665 while(1) {
666 if(sst1InitCheckBoard((FxU32 *) sstSlave) == FXFALSE)
667 return(FXFALSE);
668 // Turn off scanline interleaving and snooping in slave...
669 PCICFG_RD(SST1_PCI_INIT_ENABLE, j);
670 PCICFG_WR(SST1_PCI_INIT_ENABLE, j & ~(SST_SCANLINE_SLV_OWNPCI |
671 SST_SCANLINE_SLI_SLV | SST_SLI_SNOOP_EN |
672 SST_SLI_SNOOP_MEMBASE));
673 ISET(sstSlave->fbiInit1, IGET(sstSlave->fbiInit1) &
674 ~SST_EN_SCANLINE_INTERLEAVE);
675 sst1InitIdle((FxU32 *) sstSlave);
676
677 if(IGET(sstSlave->fbiInit1) & SST_EN_SCANLINE_INTERLEAVE) {
678 if(++cntr < 10)
679 continue;
680 else {
681 INIT_PRINTF(("sst1InitShutdown(): Could not disable Slave SLI...\n"));
682 return(FXFALSE);
683 }
684 }
685 break;
686 }
687 if(sst1InitCheckBoard((FxU32 *) sstMaster) == FXFALSE)
688 return(FXFALSE);
689 ISET(sstMaster->fbiInit1, IGET(sstMaster->fbiInit1) &
690 ~SST_EN_SCANLINE_INTERLEAVE);
691 sst1InitIdle((FxU32 *) sstMaster);
692 }
693 return(FXTRUE);
694}
695
696/*
697** sst1InitSliDetect():
698** Determine if scanline interleave has been detected (either through
699** power-up settings or through SST_SLIDETECT)
700**
701*/
702FX_ENTRY FxU32 FX_CALL sst1InitSliDetect(FxU32 *sstbase)
703{
704 FxU32 sliDetected;
705
706 if(GETENV(("SSTV2_SLIDETECT")))
707 sliDetected = ATOI(GETENV(("SSTV2_SLIDETECT")));
708 else
709 sliDetected = sst1InitSliPaired(sstbase);
710
711 return sliDetected;
712 }
713
714/*
715** sst1InitSliPaired():
716** Determine if scanline interleave has been detected through
717** power-up settings.
718**
719*/
720FX_ENTRY FxU32 FX_CALL
721sst1InitSliPaired(FxU32 *sstbase)
722{
723 static int firstTime = 1;
724 static FxU32 sliPaired = 0;
725
726 if(firstTime) {
727 SstRegs* sst = (SstRegs *) sstbase;
728
729 sliPaired = (((IGET(sst->fbiInit5) & SST_SLI_DETECT) == SST_SLI_DETECT) &&
730 (boardsInSystem > 1));
731 firstTime = 0;
732 }
733
734 return sliPaired;
735}
736
737#pragma optimize ("",on)
Note: See TracBrowser for help on using the repository browser.