1 /* 2 Copyright (c) 2002, Thomas Kurschel 3 4 5 Part of Radeon accelerant 6 7 CP initialization/sync/cleanup. 8 9 It also handles command buffer synchronization. 10 11 non-local memory is used as following: 12 - 2048 dwords for ring buffer 13 - 253 indirect buffers a 4k (1024 dwords) 14 - 8 dwords for returned data (i.e. current read ptr) 15 & 6 dwords for "scratch registers" 16 17 usage of scratch registers: 18 - reg 0 = reached engine.count 19 20 with a granularity of 4 KByte, we need 2+253+1=256 blocks, which is exactly 1 MB 21 */ 22 23 #include "radeon_driver.h" 24 #include "CPMicroCode.h" 25 #include "mmio.h" 26 #include "cp_regs.h" 27 #include "pll_regs.h" 28 #include "rbbm_regs.h" 29 #include "buscntrl_regs.h" 30 #include "utils.h" 31 #include "pll_access.h" 32 33 #include "log_coll.h" 34 #include "log_enum.h" 35 36 #include <string.h> 37 38 #if 0 39 40 // macros for user-space 41 42 #define ALLOC_MEM( asize, mem_type, aglobal, handle, offset ) \ 43 { \ 44 radeon_alloc_mem am; \ 45 \ 46 am.magic = RADEON_PRIVATE_DATA_MAGIC; \ 47 am.size = (asize) * 4; \ 48 am.memory_type = (mt_nonlocal); \ 49 am.global = (aglobal); \ 50 \ 51 res = ioctl( ai->fd, RADEON_ALLOC_MEM, &am ); \ 52 if( res == B_OK ) \ 53 *(handle) = am.handle; \ 54 *(offset) = am.offset; \ 55 } 56 57 #define MEM2CPU( mem ) \ 58 ((uint32 *)(ai->mapped_memory[(mem).memory_type].data + (mem).offset)) 59 60 #define MEM2GC( mem ) ((mem).offset + si->memory[(mem).memory_type].virtual_addr_start) 61 62 #define FREE_MEM( mem_type, handle ) \ 63 { \ 64 radeon_free_mem fm; \ 65 \ 66 fm.magic = RADEON_PRIVATE_DATA_MAGIC; \ 67 fm.memory_type = mem_type; \ 68 fm.handle = offset; \ 69 \ 70 ioctl( ai->fd, RADEON_FREE_MEM, &fm ); \ 71 } 72 73 #else 74 75 // macros for kernel-space 76 77 // allocate memory 78 // if memory_type is non-local, it is replaced with default non-local type 79 #define ALLOC_MEM( asize, mem_type, aglobal, handle, offset ) \ 80 if( mem_type == mt_nonlocal ) \ 81 mem_type = di->si->nonlocal_type; \ 82 res = mem_alloc( di->memmgr[mem_type], asize, NULL, handle, offset ); 83 84 // get address as seen by program to access allocated memory 85 // (memory_type must _not_ be non-local, see ALLOC_MEM) 86 #define MEM2CPU( memory_type, offset ) \ 87 ((uint8 *)(memory_type == mt_local ? di->si->local_mem : \ 88 (memory_type == mt_PCI ? di->pci_gart.buffer.ptr : di->agp_gart.buffer.ptr)) \ 89 + (offset)) 90 91 // get graphics card's virtual address of allocated memory 92 // (memory_type must _not_ be non-local, see ALLOC_MEM) 93 #define MEM2GC( memory_type, offset ) \ 94 (di->si->memory[(memory_type)].virtual_addr_start + (offset)) 95 96 // free memory 97 // if memory_type is non-local, it is replaced with default non-local type 98 #define FREE_MEM( mem_type, handle ) \ 99 mem_free( \ 100 di->memmgr[ mem_type == mt_nonlocal ? di->si->nonlocal_type : mem_type], \ 101 handle, NULL ); 102 103 #endif 104 105 106 void Radeon_DiscardAllIndirectBuffers( device_info *di ); 107 108 #define RADEON_SCRATCH_REG_OFFSET 32 109 110 111 void Radeon_FlushPixelCache( device_info *di ); 112 113 // wait until engine is idle; 114 // acquire_lock - true, if lock must be hold 115 // false, if lock is already acquired 116 // keep_lock - true, keep lock on exit (only valid if acquire_lock is true) 117 void Radeon_WaitForIdle( device_info *di, bool acquire_lock, bool keep_lock ) 118 { 119 if( acquire_lock ) 120 ACQUIRE_BEN( di->si->cp.lock ); 121 122 Radeon_WaitForFifo( di, 64 ); 123 124 while( 1 ) { 125 bigtime_t start_time = system_time(); 126 127 do { 128 if( (INREG( di->regs, RADEON_RBBM_STATUS ) & RADEON_RBBM_ACTIVE) == 0 ) { 129 Radeon_FlushPixelCache( di ); 130 131 if( acquire_lock && !keep_lock) 132 RELEASE_BEN( di->si->cp.lock ); 133 134 return; 135 } 136 137 snooze( 1 ); 138 } while( system_time() - start_time < 1000000 ); 139 140 SHOW_ERROR( 3, "Engine didn't become idle (rbbm_status=%lx, cp_stat=%lx, tlb_address=%lx, tlb_data=%lx)", 141 INREG( di->regs, RADEON_RBBM_STATUS ), 142 INREG( di->regs, RADEON_CP_STAT ), 143 INREG( di->regs, RADEON_AIC_TLB_ADDR ), 144 INREG( di->regs, RADEON_AIC_TLB_DATA )); 145 146 LOG( di->si->log, _Radeon_WaitForIdle ); 147 148 Radeon_ResetEngine( di ); 149 } 150 } 151 152 153 // wait until "entries" FIFO entries are empty 154 // lock must be hold 155 void Radeon_WaitForFifo( device_info *di, int entries ) 156 { 157 while( 1 ) { 158 bigtime_t start_time = system_time(); 159 160 do { 161 int slots = INREG( di->regs, RADEON_RBBM_STATUS ) & RADEON_RBBM_FIFOCNT_MASK; 162 163 if ( slots >= entries ) 164 return; 165 166 snooze( 1 ); 167 } while( system_time() - start_time < 1000000 ); 168 169 LOG( di->si->log, _Radeon_WaitForFifo ); 170 171 Radeon_ResetEngine( di ); 172 } 173 } 174 175 // flush pixel cache of graphics card 176 void Radeon_FlushPixelCache( device_info *di ) 177 { 178 bigtime_t start_time; 179 180 OUTREGP( di->regs, RADEON_RB2D_DSTCACHE_CTLSTAT, RADEON_RB2D_DC_FLUSH_ALL, 181 ~RADEON_RB2D_DC_FLUSH_ALL ); 182 183 start_time = system_time(); 184 185 do { 186 if( (INREG( di->regs, RADEON_RB2D_DSTCACHE_CTLSTAT ) 187 & RADEON_RB2D_DC_BUSY) == 0 ) 188 return; 189 190 snooze( 1 ); 191 } while( system_time() - start_time < 1000000 ); 192 193 LOG( di->si->log, _Radeon_FlushPixelCache ); 194 195 SHOW_ERROR0( 0, "pixel cache didn't become empty" ); 196 } 197 198 // reset graphics card's engine 199 // lock must be hold 200 void Radeon_ResetEngine( device_info *di ) 201 { 202 vuint8 *regs = di->regs; 203 shared_info *si = di->si; 204 uint32 clock_cntl_index, mclk_cntl, rbbm_soft_reset, host_path_cntl; 205 uint32 cur_read_ptr; 206 207 SHOW_FLOW0( 3, "" ); 208 209 Radeon_FlushPixelCache( di ); 210 211 clock_cntl_index = INREG( regs, RADEON_CLOCK_CNTL_INDEX ); 212 R300_PLLFix( di->regs, di->asic ); 213 214 // OUCH! 215 // XFree disables any kind of automatic power power management 216 // because of bugs of some ASIC revision (seems like the revisions 217 // cannot be read out) 218 // -> this is a very bad idea, especially when it comes to laptops 219 // I comment it out for now, let's hope noone takes notice 220 if( di->num_crtc > 1 ) { 221 Radeon_OUTPLLP( regs, di->asic, RADEON_SCLK_CNTL, 222 RADEON_CP_MAX_DYN_STOP_LAT | 223 RADEON_SCLK_FORCEON_MASK, 224 ~RADEON_DYN_STOP_LAT_MASK ); 225 226 /* if( ai->si->asic == rt_rv200 ) { 227 Radeon_OUTPLLP( ai, RADEON_SCLK_MORE_CNTL, 228 RADEON_SCLK_MORE_FORCEON, ~0 ); 229 }*/ 230 } 231 232 mclk_cntl = Radeon_INPLL( regs, di->asic, RADEON_MCLK_CNTL ); 233 234 // enable clock of units to be reset 235 Radeon_OUTPLL( regs, di->asic, RADEON_MCLK_CNTL, mclk_cntl | 236 RADEON_FORCEON_MCLKA | 237 RADEON_FORCEON_MCLKB | 238 RADEON_FORCEON_YCLKA | 239 RADEON_FORCEON_YCLKB | 240 RADEON_FORCEON_MC | 241 RADEON_FORCEON_AIC ); 242 243 // do the reset 244 host_path_cntl = INREG( regs, RADEON_HOST_PATH_CNTL ); 245 rbbm_soft_reset = INREG( regs, RADEON_RBBM_SOFT_RESET ); 246 247 switch( di->asic ) { 248 case rt_r300: 249 OUTREG( regs, RADEON_RBBM_SOFT_RESET, (rbbm_soft_reset | 250 RADEON_SOFT_RESET_CP | 251 RADEON_SOFT_RESET_HI | 252 RADEON_SOFT_RESET_E2 | 253 RADEON_SOFT_RESET_AIC )); 254 INREG( regs, RADEON_RBBM_SOFT_RESET); 255 OUTREG( regs, RADEON_RBBM_SOFT_RESET, 0); 256 // this bit has no description 257 OUTREGP( regs, RADEON_RB2D_DSTCACHE_MODE, (1 << 17), ~0 ); 258 259 break; 260 default: 261 OUTREG( regs, RADEON_RBBM_SOFT_RESET, rbbm_soft_reset | 262 RADEON_SOFT_RESET_CP | 263 RADEON_SOFT_RESET_HI | 264 RADEON_SOFT_RESET_SE | 265 RADEON_SOFT_RESET_RE | 266 RADEON_SOFT_RESET_PP | 267 RADEON_SOFT_RESET_E2 | 268 RADEON_SOFT_RESET_RB | 269 RADEON_SOFT_RESET_AIC ); 270 INREG( regs, RADEON_RBBM_SOFT_RESET ); 271 OUTREG( regs, RADEON_RBBM_SOFT_RESET, rbbm_soft_reset & 272 ~( RADEON_SOFT_RESET_CP | 273 RADEON_SOFT_RESET_HI | 274 RADEON_SOFT_RESET_SE | 275 RADEON_SOFT_RESET_RE | 276 RADEON_SOFT_RESET_PP | 277 RADEON_SOFT_RESET_E2 | 278 RADEON_SOFT_RESET_RB | 279 RADEON_SOFT_RESET_AIC ) ); 280 INREG( regs, RADEON_RBBM_SOFT_RESET ); 281 } 282 283 OUTREG( regs, RADEON_HOST_PATH_CNTL, host_path_cntl | RADEON_HDP_SOFT_RESET ); 284 INREG( regs, RADEON_HOST_PATH_CNTL ); 285 OUTREG( regs, RADEON_HOST_PATH_CNTL, host_path_cntl ); 286 287 // restore regs 288 OUTREG( regs, RADEON_RBBM_SOFT_RESET, rbbm_soft_reset); 289 290 OUTREG( regs, RADEON_CLOCK_CNTL_INDEX, clock_cntl_index ); 291 R300_PLLFix( regs, di->asic ); 292 Radeon_OUTPLL( regs, di->asic, RADEON_MCLK_CNTL, mclk_cntl ); 293 294 // reset ring buffer 295 cur_read_ptr = INREG( regs, RADEON_CP_RB_RPTR ); 296 OUTREG( regs, RADEON_CP_RB_WPTR, cur_read_ptr ); 297 298 //if( si->cp.ring.head ) { 299 // during init, there are no feedback data 300 if( si->cp.feedback.mem_handle != 0 ) { 301 *(uint32 *)MEM2CPU( si->cp.feedback.mem_type, si->cp.feedback.head_mem_offset) = 302 cur_read_ptr; 303 // *si->cp.ring.head = cur_read_ptr; 304 si->cp.ring.tail = cur_read_ptr; 305 } 306 307 ++si->engine.count; 308 309 // mark all buffers as being finished 310 Radeon_DiscardAllIndirectBuffers( di ); 311 312 return; 313 } 314 315 316 // upload Micro-Code of CP 317 static void loadMicroEngineRAMData( device_info *di ) 318 { 319 int i; 320 const uint32 (*microcode)[2]; 321 322 SHOW_FLOW0( 3, "" ); 323 324 switch( di->asic ) { 325 case rt_r300: 326 case rt_r300_4p: 327 case rt_rv350: 328 case rt_rv360: 329 case rt_r350: 330 case rt_r360: 331 microcode = r300_cp_microcode; 332 break; 333 case rt_r200: 334 //case rt_rv250: 335 //case rt_m9: 336 microcode = r200_cp_microcode; 337 break; 338 case rt_rs100: 339 default: 340 microcode = radeon_cp_microcode; 341 } 342 343 Radeon_WaitForIdle( di, false, false ); 344 345 /* 346 // HACK start 347 Radeon_ResetEngine( di ); 348 OUTREG( di->regs, 0x30, 0x5133a3a0 ); // bus_cntl 349 OUTREGP( di->regs, 0xf0c, 0xff00, ~0xff ); // latency 350 Radeon_WaitForIdle( di, false, false ); 351 Radeon_ResetEngine( di ); 352 // HACK end 353 */ 354 355 OUTREG( di->regs, RADEON_CP_ME_RAM_ADDR, 0 ); 356 357 for ( i = 0 ; i < 256 ; i++ ) { 358 OUTREG( di->regs, RADEON_CP_ME_RAM_DATAH, microcode[i][1] ); 359 OUTREG( di->regs, RADEON_CP_ME_RAM_DATAL, microcode[i][0] ); 360 } 361 } 362 363 // aring_size - size of ring in dwords 364 static status_t initRingBuffer( device_info *di, int aring_size ) 365 { 366 status_t res; 367 shared_info *si = di->si; 368 CP_info *cp = &si->cp; 369 vuint8 *regs = di->regs; 370 int32 offset; 371 memory_type_e memory_type; 372 373 memset( &cp->ring, 0, sizeof( cp->ring )); 374 375 // ring and indirect buffers can be either in AGP or PCI GART 376 // (it seems that they cannot be in graphics memory, at least 377 // I had serious coherency problems when I tried that) 378 memory_type = mt_nonlocal; 379 380 ALLOC_MEM( aring_size * 4, memory_type, true, 381 &cp->ring.mem_handle, &offset ); 382 383 if( res != B_OK ) { 384 SHOW_ERROR0( 0, "Cannot allocate ring buffer" ); 385 return res; 386 } 387 388 // setup CP buffer 389 cp->ring.mem_type = memory_type; 390 cp->ring.mem_offset = offset; 391 cp->ring.vm_base = MEM2GC( memory_type, offset ); 392 cp->ring.size = aring_size; 393 cp->ring.tail_mask = aring_size - 1; 394 OUTREG( regs, RADEON_CP_RB_BASE, cp->ring.vm_base ); 395 SHOW_INFO( 3, "CP buffer address=%lx", cp->ring.vm_base ); 396 397 // set ring buffer size 398 // (it's log2 of qwords) 399 OUTREG( regs, RADEON_CP_RB_CNTL, log2( cp->ring.size / 2 )); 400 SHOW_INFO( 3, "CP buffer size mask=%d", log2( cp->ring.size / 2 ) ); 401 402 // set write pointer delay to zero; 403 // we assume that memory synchronization is done correctly my MoBo 404 // and Radeon_SendCP contains a hack that hopefully fixes such problems 405 OUTREG( regs, RADEON_CP_RB_WPTR_DELAY, 0 ); 406 407 memset( MEM2CPU( cp->ring.mem_type, cp->ring.mem_offset), 0, cp->ring.size * 4 ); 408 409 // set CP buffer pointers 410 OUTREG( regs, RADEON_CP_RB_RPTR, 0 ); 411 OUTREG( regs, RADEON_CP_RB_WPTR, 0 ); 412 //*cp->ring.head = 0; 413 cp->ring.tail = 0; 414 415 return B_OK; 416 } 417 418 static void uninitRingBuffer( device_info *di ) 419 { 420 vuint8 *regs = di->regs; 421 422 // abort any activity 423 Radeon_ResetEngine( di ); 424 425 // disable CP BM 426 OUTREG( regs, RADEON_CP_CSQ_CNTL, RADEON_CSQ_PRIDIS_INDDIS ); 427 // read-back for flushing 428 INREG( regs, RADEON_CP_CSQ_CNTL ); 429 430 FREE_MEM( mt_nonlocal, di->si->cp.ring.mem_handle ); 431 } 432 433 static status_t initCPFeedback( device_info *di ) 434 { 435 CP_info *cp = &di->si->cp; 436 vuint8 *regs = di->regs; 437 int32 offset; 438 memory_type_e memory_type; 439 status_t res; 440 441 // status information should be in PCI memory, so CPU can 442 // poll it without locking the bus (PCI memory is the only 443 // cachable memory available) 444 memory_type = mt_PCI; 445 446 ALLOC_MEM( RADEON_SCRATCH_REG_OFFSET + 0x40, memory_type, true, 447 &cp->feedback.mem_handle, &offset ); 448 449 if( res != B_OK ) { 450 SHOW_ERROR0( 0, "Cannot allocate buffers for status information" ); 451 return res; 452 } 453 454 // setup CP read pointer buffer 455 cp->feedback.mem_type = memory_type; 456 cp->feedback.head_mem_offset = offset; 457 cp->feedback.head_vm_address = MEM2GC( memory_type, cp->feedback.head_mem_offset ); 458 OUTREG( regs, RADEON_CP_RB_RPTR_ADDR, cp->feedback.head_vm_address ); 459 SHOW_INFO( 3, "CP read pointer buffer==%lx", cp->feedback.head_vm_address ); 460 461 // setup scratch register buffer 462 cp->feedback.scratch_mem_offset = offset + RADEON_SCRATCH_REG_OFFSET; 463 cp->feedback.scratch_vm_start = MEM2GC( memory_type, cp->feedback.scratch_mem_offset ); 464 OUTREG( regs, RADEON_SCRATCH_ADDR, cp->feedback.scratch_vm_start ); 465 OUTREG( regs, RADEON_SCRATCH_UMSK, 0x3f ); 466 467 *(uint32 *)MEM2CPU( cp->feedback.mem_type, cp->feedback.head_mem_offset) = 0; 468 memset( MEM2CPU( cp->feedback.mem_type, cp->feedback.scratch_mem_offset), 0, 0x40 ); 469 //*cp->ring.head = 0; 470 471 return B_OK; 472 } 473 474 static void uninitCPFeedback( device_info *di ) 475 { 476 vuint8 *regs = di->regs; 477 478 // don't allow any scratch buffer update 479 OUTREG( regs, RADEON_SCRATCH_UMSK, 0x0 ); 480 481 FREE_MEM( mt_PCI, di->si->cp.feedback.mem_handle ); 482 } 483 484 static status_t initIndirectBuffers( device_info *di ) 485 { 486 CP_info *cp = &di->si->cp; 487 int32 offset; 488 memory_type_e memory_type; 489 int i; 490 status_t res; 491 492 memory_type = mt_nonlocal; 493 494 ALLOC_MEM( NUM_INDIRECT_BUFFERS * INDIRECT_BUFFER_SIZE * 4, memory_type, 495 true, &cp->buffers.mem_handle, &offset ); 496 497 if( res != B_OK ) { 498 SHOW_ERROR0( 0, "Cannot allocate indirect buffers" ); 499 return B_ERROR; 500 } 501 502 cp->buffers.mem_type = memory_type; 503 cp->buffers.mem_offset = offset; 504 cp->buffers.vm_start = MEM2GC( memory_type, cp->buffers.mem_offset ); 505 506 for( i = 0; i < NUM_INDIRECT_BUFFERS - 1; ++i ) { 507 cp->buffers.buffers[i].next = i + 1; 508 } 509 510 cp->buffers.buffers[i].next = -1; 511 512 cp->buffers.free_list = 0; 513 cp->buffers.oldest = -1; 514 cp->buffers.newest = -1; 515 cp->buffers.active_state = -1; 516 cp->buffers.cur_tag = 0; 517 518 memset( MEM2CPU( cp->buffers.mem_type, cp->buffers.mem_offset), 0, 519 NUM_INDIRECT_BUFFERS * INDIRECT_BUFFER_SIZE * 4 ); 520 521 return B_OK; 522 } 523 524 static void uninitIndirectBuffers( device_info *di ) 525 { 526 FREE_MEM( mt_nonlocal, di->si->cp.buffers.mem_handle ); 527 } 528 529 // initialize CP so it's ready for BM 530 status_t Radeon_InitCP( device_info *di ) 531 { 532 thread_id thid; 533 thread_info thinfo; 534 status_t res; 535 536 SHOW_FLOW0( 3, "" ); 537 538 // this is _really_ necessary so functions like ResetEngine() know 539 // that the CP is not set up yet 540 memset( &di->si->cp, 0, sizeof( di->si->cp )); 541 542 if( (res = INIT_BEN( di->si->cp.lock, "Radeon CP" )) < 0 ) 543 return res; 544 545 // HACK: change owner of benaphore semaphore to team of calling thread; 546 // reason: user code cannot acquire kernel semaphores, but the accelerant 547 // is in user space; interestingly, it's enough to change the semaphore's 548 // owner to _any_ non-system team (that's the only security check done by 549 // the kernel) 550 thid = find_thread( NULL ); 551 get_thread_info( thid, &thinfo ); 552 set_sem_owner( di->si->cp.lock.sem, thinfo.team ); 553 554 // init raw CP 555 loadMicroEngineRAMData( di ); 556 557 // do soft-reset 558 Radeon_ResetEngine( di ); 559 560 // after warm-reset, the CP may still be active and thus react to 561 // register writes during initialization unpredictably, so we better 562 // stop it first 563 OUTREG( di->regs, RADEON_CP_CSQ_CNTL, RADEON_CSQ_PRIDIS_INDDIS ); 564 INREG( di->regs, RADEON_CP_CSQ_CNTL ); 565 566 // reset CP to make disabling active 567 Radeon_ResetEngine( di ); 568 569 res = initRingBuffer( di, CP_RING_SIZE ); 570 if( res < 0 ) 571 goto err4; 572 573 res = initCPFeedback( di ); 574 if( res < 0 ) 575 goto err3; 576 577 res = initIndirectBuffers( di ); 578 if( res < 0 ) 579 goto err2; 580 581 // tell CP to use BM 582 Radeon_WaitForIdle( di, false, false ); 583 584 // enable direct and indirect CP bus mastering 585 OUTREG( di->regs, RADEON_CP_CSQ_CNTL, RADEON_CSQ_PRIBM_INDBM ); 586 587 // allow bus mastering in general 588 OUTREGP( di->regs, RADEON_BUS_CNTL, 0, ~RADEON_BUS_MASTER_DIS ); 589 590 // don't allow mixing of 2D/3D/scratch/wait_until commands 591 // (in fact, this doesn't seem to make any difference as we do a 592 // manual sync in all these cases anyway) 593 OUTREG( di->regs, RADEON_ISYNC_CNTL, 594 RADEON_ISYNC_ANY2D_IDLE3D | 595 RADEON_ISYNC_ANY3D_IDLE2D | 596 RADEON_ISYNC_WAIT_IDLEGUI | 597 RADEON_ISYNC_CPSCRATCH_IDLEGUI ); 598 599 SHOW_FLOW( 3, "bus_cntl=%lx", INREG( di->regs, RADEON_BUS_CNTL )); 600 601 SHOW_FLOW0( 3, "Done" ); 602 603 return B_OK; 604 605 //err: 606 // uninitIndirectBuffers( ai ); 607 err2: 608 uninitCPFeedback( di ); 609 err3: 610 uninitRingBuffer( di ); 611 err4: 612 DELETE_BEN( di->si->cp.lock ); 613 return res; 614 } 615 616 617 // shutdown CP, freeing any memory 618 void Radeon_UninitCP( device_info *di ) 619 { 620 vuint8 *regs = di->regs; 621 622 // abort any pending commands 623 Radeon_ResetEngine( di ); 624 625 // disable CP BM 626 OUTREG( regs, RADEON_CP_CSQ_CNTL, RADEON_CSQ_PRIDIS_INDDIS ); 627 // read-back for flushing 628 INREG( regs, RADEON_CP_CSQ_CNTL ); 629 630 uninitRingBuffer( di ); 631 uninitCPFeedback( di ); 632 uninitIndirectBuffers( di ); 633 634 DELETE_BEN( di->si->cp.lock ); 635 } 636 637 638 // mark all indirect buffers as being free; 639 // this should only be called after a reset; 640 // lock must be hold 641 void Radeon_DiscardAllIndirectBuffers( device_info *di ) 642 { 643 CP_info *cp = &di->si->cp; 644 645 // during init, there is no indirect buffer 646 if( cp->buffers.mem_handle == 0 ) 647 return; 648 649 // mark all sent indirect buffers as free 650 while( cp->buffers.oldest != -1 ) { 651 indirect_buffer *oldest_buffer = 652 &cp->buffers.buffers[cp->buffers.oldest]; 653 int tmp_oldest_buffer; 654 655 SHOW_FLOW( 0, "%d", cp->buffers.oldest ); 656 657 // remove buffer from "used" list 658 tmp_oldest_buffer = oldest_buffer->next; 659 660 if( tmp_oldest_buffer == -1 ) 661 cp->buffers.newest = -1; 662 663 // put it on free list 664 oldest_buffer->next = cp->buffers.free_list; 665 cp->buffers.free_list = cp->buffers.oldest; 666 667 cp->buffers.oldest = tmp_oldest_buffer; 668 } 669 } 670