1 /*
2 Copyright (c) 2002-05, Thomas Kurschel
3
4
5 Part of Radeon accelerant
6
7 Access to VIP
8
9 This code must be in kernel because we need for FIFO to become empty
10 during VIP access (which in turn requires locking the card, and locking
11 is a dangerous thing in user mode as the app can suddenly die, taking
12 the lock with it)
13 */
14
15 #include "radeon_driver.h"
16 #include "mmio.h"
17 #include "vip_regs.h"
18 #include "bios_regs.h"
19 #include "theatre_regs.h"
20
21
22 // moved to bottom to avoid inlining
23 static bool Radeon_VIPWaitForIdle( device_info *di );
24 static status_t RADEON_VIPFifoIdle(device_info *di, uint8 channel);
25
26
27 // read data from VIP
28 // CP lock must be hold
do_VIPRead(device_info * di,uint channel,uint address,uint32 * data)29 static bool do_VIPRead(
30 device_info *di, uint channel, uint address, uint32 *data )
31 {
32 vuint8 *regs = di->regs;
33
34 Radeon_WaitForFifo( di, 2 );
35 // the 0x2000 is the nameless "register-read" flag
36 OUTREG( regs, RADEON_VIPH_REG_ADDR, (channel << 14) | address | 0x2000 );
37
38 if( !Radeon_VIPWaitForIdle( di ))
39 return false;
40
41 // enable VIP register cycle reads
42 Radeon_WaitForFifo( di, 2 );
43 OUTREGP( regs, RADEON_VIPH_TIMEOUT_STAT, 0,
44 ~RADEON_VIPH_TIMEOUT_STAT_AK_MASK & ~RADEON_VIPH_TIMEOUT_STAT_VIPH_REGR_DIS );
45 //Radeon_WaitForIdle( di, false, false );
46
47 // this read starts a register cycle; the returned value has no meaning
48 INREG( regs, RADEON_VIPH_REG_DATA );
49
50 if( !Radeon_VIPWaitForIdle( di ))
51 return false;
52
53 //Radeon_WaitForIdle( di, false, false );
54
55 // register cycle is done, so disable any further cycle
56 Radeon_WaitForFifo( di, 2 );
57 OUTREGP( regs, RADEON_VIPH_TIMEOUT_STAT, RADEON_VIPH_TIMEOUT_STAT_VIPH_REGR_DIS,
58 ~RADEON_VIPH_TIMEOUT_STAT_AK_MASK & ~RADEON_VIPH_TIMEOUT_STAT_VIPH_REGR_DIS );
59 //Radeon_WaitForIdle( di, false, false );
60
61 // get the data
62 *data = INREG( regs, RADEON_VIPH_REG_DATA );
63
64 //SHOW_FLOW( 4, "channel=%d, address=%x, data=%lx", channel, address, *data );
65
66 if( !Radeon_VIPWaitForIdle( di ))
67 return false;
68
69 // disable register cycle again (according to sample code)
70 // IMHO, this is not necessary as it has been done before
71 Radeon_WaitForFifo( di, 2 );
72 OUTREGP( regs, RADEON_VIPH_TIMEOUT_STAT, RADEON_VIPH_TIMEOUT_STAT_VIPH_REGR_DIS,
73 ~RADEON_VIPH_TIMEOUT_STAT_AK_MASK & ~RADEON_VIPH_TIMEOUT_STAT_VIPH_REGR_DIS );
74
75 return true;
76 }
77
78 // public function: read data from VIP
Radeon_VIPRead(device_info * di,uint channel,uint address,uint32 * data,bool lock)79 bool Radeon_VIPRead(
80 device_info *di, uint channel, uint address, uint32 *data, bool lock )
81 {
82 bool res;
83
84 if( lock )
85 ACQUIRE_BEN( di->si->cp.lock );
86
87 res = do_VIPRead( di, channel, address, data );
88
89 if( lock )
90 RELEASE_BEN( di->si->cp.lock );
91
92 // SHOW_FLOW( 2, "address=%x, data=%lx, lock=%d", address, *data, lock );
93
94 return res;
95 }
96
do_VIPFifoRead(device_info * di,uint8 channel,uint32 address,uint32 count,uint8 * buffer)97 static bool do_VIPFifoRead(device_info *di, uint8 channel, uint32 address, uint32 count, uint8 *buffer)
98 {
99 vuint8 *regs = di->regs;
100 uint32 status, tmp;
101
102 if(count!=1)
103 {
104 SHOW_FLOW0( 2, "Attempt to access VIP bus with non-stadard transaction length\n");
105 return false;
106 }
107
108 SHOW_FLOW( 2, "address=%" B_PRIx32 ", count=%" B_PRIu32 " ",
109 address, count );
110
111 Radeon_WaitForFifo( di, 2);
112 SHOW_FLOW0( 2, "1");
113 OUTREG( regs, RADEON_VIPH_REG_ADDR, (channel << 14) | address | 0x3000);
114 SHOW_FLOW0( 2, "3");
115 while(B_BUSY == (status = RADEON_VIPFifoIdle( di , 0xff)));
116 if(B_OK != status) return false;
117
118 // disable VIPH_REGR_DIS to enable VIP cycle.
119 // The LSB of VIPH_TIMEOUT_STAT are set to 0
120 // because 1 would have acknowledged various VIP
121 // interrupts unexpectedly
122
123 SHOW_FLOW0( 2, "4");
124 Radeon_WaitForFifo( di, 2 ); // Radeon_WaitForIdle( di, false, false );
125 SHOW_FLOW0( 2, "5");
126 OUTREG( regs, RADEON_VIPH_TIMEOUT_STAT,
127 INREG( regs, RADEON_VIPH_TIMEOUT_STAT) &
128 (0xffffff00 & ~RADEON_VIPH_TIMEOUT_STAT_VIPH_REGR_DIS) );
129
130 // the value returned here is garbage. The read merely initiates
131 // a register cycle
132 SHOW_FLOW0( 2, "6");
133 Radeon_WaitForFifo( di, 2 ); // Radeon_WaitForIdle( di, false, false );
134 INREG( regs, RADEON_VIPH_REG_DATA);
135 SHOW_FLOW0( 2, "7");
136 while(B_BUSY == (status = RADEON_VIPFifoIdle( di , 0xff)));
137 if(B_OK != status) return false;
138
139 // set VIPH_REGR_DIS so that the read won't take too long.
140 SHOW_FLOW0( 2, "8");
141 Radeon_WaitForFifo( di, 2 ); // Radeon_WaitForIdle( di, false, false );
142 SHOW_FLOW0( 2, "9");
143 tmp = INREG( regs, RADEON_VIPH_TIMEOUT_STAT);
144 OUTREG( regs, RADEON_VIPH_TIMEOUT_STAT, (tmp & 0xffffff00) | RADEON_VIPH_TIMEOUT_STAT_VIPH_REGR_DIS);
145
146 SHOW_FLOW0( 2, "10");
147 Radeon_WaitForFifo( di, 2 ); // Radeon_WaitForIdle( di, false, false );
148 switch(count){
149 case 1:
150 *buffer=(uint8)(INREG( regs, RADEON_VIPH_REG_DATA) & 0xff);
151 break;
152 case 2:
153 *(uint16 *)buffer=(uint16) (INREG( regs, RADEON_VIPH_REG_DATA) & 0xffff);
154 break;
155 case 4:
156 *(uint32 *)buffer=(uint32) ( INREG( regs, RADEON_VIPH_REG_DATA) & 0xffffffff);
157 break;
158 }
159 SHOW_FLOW0( 2, "11");
160 while(B_BUSY == (status = RADEON_VIPFifoIdle( di , 0xff)));
161 if(B_OK != status) return false;
162
163 // so that reading VIPH_REG_DATA would not trigger unnecessary vip cycles.
164 SHOW_FLOW0( 2, "12");
165 OUTREG( regs, RADEON_VIPH_TIMEOUT_STAT,
166 (INREG( regs, RADEON_VIPH_TIMEOUT_STAT) & 0xffffff00) | RADEON_VIPH_TIMEOUT_STAT_VIPH_REGR_DIS);
167 return true;
168
169 }
170
Radeon_VIPFifoRead(device_info * di,uint8 channel,uint32 address,uint32 count,uint8 * buffer,bool lock)171 bool Radeon_VIPFifoRead(device_info *di, uint8 channel, uint32 address, uint32 count, uint8 *buffer, bool lock)
172 {
173 bool res;
174
175 if( lock )
176 ACQUIRE_BEN( di->si->cp.lock );
177
178 res = do_VIPFifoRead( di, channel, address, count, buffer );
179
180 if( lock )
181 RELEASE_BEN( di->si->cp.lock );
182
183 //SHOW_FLOW( 2, "address=%x, data=%lx, lock=%d", address, *data, lock );
184
185 return res;
186 }
187
188 // write data to VIP
189 // CP must be hold
do_VIPWrite(device_info * di,uint8 channel,uint address,uint32 data)190 static bool do_VIPWrite( device_info *di, uint8 channel, uint address, uint32 data )
191 {
192 vuint8 *regs = di->regs;
193
194 Radeon_WaitForFifo( di, 2 );
195 OUTREG( regs, RADEON_VIPH_REG_ADDR, (channel << 14) | (address & ~0x2000) );
196
197 if( !Radeon_VIPWaitForIdle( di )) return false;
198
199 //SHOW_FLOW( 4, "channel=%d, address=%x, data=%lx", channel, address, data );
200
201 Radeon_WaitForFifo( di, 2 );
202 OUTREG( regs, RADEON_VIPH_REG_DATA, data );
203
204 return Radeon_VIPWaitForIdle( di );
205
206 }
207
208 // public function: write data to VIP
Radeon_VIPWrite(device_info * di,uint8 channel,uint address,uint32 data,bool lock)209 bool Radeon_VIPWrite(device_info *di, uint8 channel, uint address, uint32 data, bool lock )
210 {
211 bool res;
212
213 //SHOW_FLOW( 2, "address=%x, data=%lx, lock=%d", address, data, lock );
214
215 if( lock )
216 ACQUIRE_BEN( di->si->cp.lock );
217
218 res = do_VIPWrite( di, channel, address, data );
219
220 if( lock )
221 RELEASE_BEN( di->si->cp.lock );
222
223 return res;
224 }
225
226
do_VIPFifoWrite(device_info * di,uint8 channel,uint32 address,uint32 count,uint8 * buffer)227 static bool do_VIPFifoWrite(device_info *di, uint8 channel, uint32 address,
228 uint32 count, uint8 *buffer)
229 {
230 vuint8 *regs = di->regs;
231
232 uint32 status;
233 uint32 i;
234
235 SHOW_FLOW( 2, "address=%" B_PRIx32 ", count=%" B_PRIu32 ", ",
236 address, count );
237
238 Radeon_WaitForFifo( di, 2 );
239 OUTREG( regs, RADEON_VIPH_REG_ADDR,
240 ((channel << 14) | address | 0x1000) & ~0x2000 );
241 SHOW_FLOW0( 2, "1");
242 do {
243 status = RADEON_VIPFifoIdle(di, 0x0f);
244 } while (status == B_BUSY);
245
246 if(B_OK != status){
247 SHOW_FLOW( 2 ,"cannot write %x to VIPH_REG_ADDR\n",
248 (unsigned int)address);
249 return false;
250 }
251
252 SHOW_FLOW0( 2, "2");
253 for (i = 0; i < count; i+=4)
254 {
255 Radeon_WaitForFifo( di, 2);
256 SHOW_FLOW( 2, "count %" B_PRIu32, count);
257 OUTREG( regs, RADEON_VIPH_REG_DATA, *(uint32*)(buffer + i));
258
259 do {
260 status = RADEON_VIPFifoIdle(di, 0x0f);
261 } while (status == B_BUSY);
262
263 if(B_OK != status)
264 {
265 SHOW_FLOW0( 2 , "cannot write to VIPH_REG_DATA\n");
266 return false;
267 }
268 }
269
270 return true;
271 }
272
Radeon_VIPFifoWrite(device_info * di,uint8 channel,uint32 address,uint32 count,uint8 * buffer,bool lock)273 bool Radeon_VIPFifoWrite(device_info *di, uint8 channel, uint32 address, uint32 count, uint8 *buffer, bool lock)
274 {
275 bool res;
276
277 //SHOW_FLOW( 2, "address=%x, data=%lx, lock=%d", address, data, lock );
278
279 if( lock )
280 ACQUIRE_BEN( di->si->cp.lock );
281
282 Radeon_VIPReset( di, false);
283 res = do_VIPFifoWrite( di, channel, address, count, buffer );
284
285 if( lock )
286 RELEASE_BEN( di->si->cp.lock );
287
288 return res;
289 }
290
291
292 // reset VIP
Radeon_VIPReset(device_info * di,bool lock)293 void Radeon_VIPReset(
294 device_info *di, bool lock )
295 {
296 vuint8 *regs = di->regs;
297
298 if( lock )
299 ACQUIRE_BEN( di->si->cp.lock );
300
301 Radeon_WaitForFifo( di, 5 ); // Radeon_WaitForIdle( di, false, false );
302 switch(di->asic){
303 case rt_r200:
304 case rt_rs200:
305 case rt_rv200:
306 case rt_rs100:
307 case rt_rv100:
308 case rt_r100:
309 OUTREG( regs, RADEON_VIPH_CONTROL, 4 | (15 << RADEON_VIPH_CONTROL_VIPH_MAX_WAIT_SHIFT) |
310 RADEON_VIPH_CONTROL_VIPH_DMA_MODE | RADEON_VIPH_CONTROL_VIPH_EN ); // slowest, timeout in 16 phases
311 OUTREG( regs, RADEON_VIPH_TIMEOUT_STAT, (INREG( regs, RADEON_VIPH_TIMEOUT_STAT) & 0xFFFFFF00) |
312 RADEON_VIPH_TIMEOUT_STAT_VIPH_REGR_DIS);
313 OUTREG( regs, RADEON_VIPH_DV_LAT,
314 0xff |
315 (4 << RADEON_VIPH_DV_LAT_VIPH_DV0_LAT_SHIFT) |
316 (4 << RADEON_VIPH_DV_LAT_VIPH_DV1_LAT_SHIFT) |
317 (4 << RADEON_VIPH_DV_LAT_VIPH_DV2_LAT_SHIFT) |
318 (4 << RADEON_VIPH_DV_LAT_VIPH_DV3_LAT_SHIFT)); // set timeslice
319 OUTREG( regs, RADEON_VIPH_DMA_CHUNK, 0x151);
320 OUTREG( regs, RADEON_TEST_DEBUG_CNTL, INREG( regs, RADEON_TEST_DEBUG_CNTL) & (~RADEON_TEST_DEBUG_CNTL_OUT_EN));
321 default:
322 OUTREG( regs, RADEON_VIPH_CONTROL, 9 | (15 << RADEON_VIPH_CONTROL_VIPH_MAX_WAIT_SHIFT) |
323 RADEON_VIPH_CONTROL_VIPH_DMA_MODE | RADEON_VIPH_CONTROL_VIPH_EN ); // slowest, timeout in 16 phases
324 OUTREG( regs, RADEON_VIPH_TIMEOUT_STAT, (INREG( regs, RADEON_VIPH_TIMEOUT_STAT) & 0xFFFFFF00) |
325 RADEON_VIPH_TIMEOUT_STAT_VIPH_REGR_DIS);
326 OUTREG( regs, RADEON_VIPH_DV_LAT,
327 0xff |
328 (4 << RADEON_VIPH_DV_LAT_VIPH_DV0_LAT_SHIFT) |
329 (4 << RADEON_VIPH_DV_LAT_VIPH_DV1_LAT_SHIFT) |
330 (4 << RADEON_VIPH_DV_LAT_VIPH_DV2_LAT_SHIFT) |
331 (4 << RADEON_VIPH_DV_LAT_VIPH_DV3_LAT_SHIFT)); // set timeslice
332 OUTREG( regs, RADEON_VIPH_DMA_CHUNK, 0x0);
333 OUTREG( regs, RADEON_TEST_DEBUG_CNTL, INREG( regs, RADEON_TEST_DEBUG_CNTL) & (~RADEON_TEST_DEBUG_CNTL_OUT_EN));
334 break;
335
336 }
337
338 if( lock )
339 RELEASE_BEN( di->si->cp.lock );
340 }
341
342
343 // check whether VIP host is idle
344 // lock must be hold
Radeon_VIPIdle(device_info * di)345 static status_t Radeon_VIPIdle(
346 device_info *di )
347 {
348 vuint8 *regs = di->regs;
349 uint32 timeout;
350
351 //Radeon_WaitForIdle( di, false, false );
352
353 // if there is a stuck transaction, acknowledge that
354 timeout = INREG( regs, RADEON_VIPH_TIMEOUT_STAT );
355 if( (timeout & RADEON_VIPH_TIMEOUT_STAT_VIPH_REG_STAT) != 0 )
356 {
357 OUTREG( regs, RADEON_VIPH_TIMEOUT_STAT,
358 (timeout & 0xffffff00) | RADEON_VIPH_TIMEOUT_STAT_VIPH_REG_AK);
359 return (INREG( regs, RADEON_VIPH_CONTROL) & 0x2000) ? B_BUSY : B_ERROR;
360 }
361 return (INREG( regs, RADEON_VIPH_CONTROL) & 0x2000) ? B_BUSY : B_OK;
362 }
363
RADEON_VIPFifoIdle(device_info * di,uint8 channel)364 static status_t RADEON_VIPFifoIdle(device_info *di, uint8 channel)
365 {
366 vuint8 *regs = di->regs;
367 uint32 timeout;
368
369 timeout = INREG( regs, RADEON_VIPH_TIMEOUT_STAT);
370 if((timeout & 0x0000000f) & channel) /* lockup ?? */
371 {
372 OUTREG( regs, RADEON_VIPH_TIMEOUT_STAT, (timeout & 0xfffffff0) | channel);
373 return (INREG( regs, RADEON_VIPH_CONTROL) & 0x2000) ? B_BUSY : B_ERROR;
374 }
375 return (INREG( regs, RADEON_VIPH_CONTROL) & 0x2000) ? B_BUSY : B_OK ;
376 }
377
378
379 // wait until VIP host is idle
380 // lock must be hold
Radeon_VIPWaitForIdle(device_info * di)381 static bool Radeon_VIPWaitForIdle(
382 device_info *di )
383 {
384 int i;
385
386 // wait 100x 1ms before giving up
387 for( i = 0; i < 100; ++i ) {
388 status_t res;
389
390 res = Radeon_VIPIdle( di );
391 if( res != B_BUSY ) {
392 if( res == B_OK )
393 return true;
394 else
395 return false;
396 }
397
398 snooze( 1000 );
399 }
400
401 return false;
402 }
403
404
405 // find VIP channel of a device
406 // return: >= 0 channel of device
407 // < 0 no device found
Radeon_FindVIPDevice(device_info * di,uint32 device_id)408 int Radeon_FindVIPDevice(
409 device_info *di, uint32 device_id )
410 {
411 uint channel;
412 uint32 cur_device_id;
413
414 // if card has no VIP port, let hardware detection fail;
415 // in this case, noone will bother us again
416 if( !di->has_vip ) {
417 SHOW_FLOW0( 3, "This Device has no VIP Bus.");
418 return -1;
419 }
420
421 ACQUIRE_BEN( di->si->cp.lock );
422
423 Radeon_VIPReset( di, false );
424
425 // there are up to 4 devices, connected to one of 4 channels
426 for( channel = 0; channel < 4; ++channel ) {
427
428 // read device id
429 if( !Radeon_VIPRead( di, channel, RADEON_VIP_VENDOR_DEVICE_ID, &cur_device_id, false )) {
430 SHOW_FLOW( 3, "No device found on channel %d", channel);
431 continue;
432 }
433
434 // compare device id directly
435 if( cur_device_id == device_id ) {
436 SHOW_FLOW( 3, "Device %08" B_PRIx32 " found on channel %d",
437 device_id, channel);
438 RELEASE_BEN( di->si->cp.lock );
439 return channel;
440 }
441 }
442
443 RELEASE_BEN( di->si->cp.lock );
444
445 // couldn't find device
446 return -1;
447 }
448