📄 cp_setup.c
字号:
//case rt_rv250: //case rt_m9: microcode = r200_cp_microcode; break; case rt_rs100: default: microcode = radeon_cp_microcode; } Radeon_WaitForIdle( di, false, false );/* // HACK start Radeon_ResetEngine( di ); OUTREG( di->regs, 0x30, 0x5133a3a0 ); // bus_cntl OUTREGP( di->regs, 0xf0c, 0xff00, ~0xff ); // latency Radeon_WaitForIdle( di, false, false ); Radeon_ResetEngine( di ); // HACK end*/ OUTREG( di->regs, RADEON_CP_ME_RAM_ADDR, 0 ); for ( i = 0 ; i < 256 ; i++ ) { OUTREG( di->regs, RADEON_CP_ME_RAM_DATAH, microcode[i][1] ); OUTREG( di->regs, RADEON_CP_ME_RAM_DATAL, microcode[i][0] ); }}// aring_size - size of ring in dwordsstatic status_t initRingBuffer( device_info *di, int aring_size ){ status_t res; shared_info *si = di->si; CP_info *cp = &si->cp; vuint8 *regs = di->regs; int32 offset; memory_type_e memory_type; memset( &cp->ring, 0, sizeof( cp->ring )); // ring and indirect buffers can be either in AGP or PCI GART // (it seems that they cannot be in graphics memory, at least // I had serious coherency problems when I tried that) memory_type = mt_nonlocal; ALLOC_MEM( aring_size * 4, memory_type, true, &cp->ring.mem_handle, &offset ); if( res != B_OK ) { SHOW_ERROR0( 0, "Cannot allocate ring buffer" ); return res; } // setup CP buffer cp->ring.mem_type = memory_type; cp->ring.mem_offset = offset; cp->ring.vm_base = MEM2GC( memory_type, offset ); cp->ring.size = aring_size; cp->ring.tail_mask = aring_size - 1; OUTREG( regs, RADEON_CP_RB_BASE, cp->ring.vm_base ); SHOW_INFO( 3, "CP buffer address=%lx", cp->ring.vm_base ); // set ring buffer size // (it's log2 of qwords) OUTREG( regs, RADEON_CP_RB_CNTL, log2( cp->ring.size / 2 )); SHOW_INFO( 3, "CP buffer size mask=%d", log2( cp->ring.size / 2 ) ); // set write pointer delay to zero; // we assume that memory synchronization is done correctly my MoBo // and Radeon_SendCP contains a hack that hopefully fixes such problems OUTREG( regs, RADEON_CP_RB_WPTR_DELAY, 0 ); memset( MEM2CPU( cp->ring.mem_type, cp->ring.mem_offset), 0, cp->ring.size * 4 ); // set CP buffer pointers OUTREG( regs, RADEON_CP_RB_RPTR, 0 ); OUTREG( regs, RADEON_CP_RB_WPTR, 0 ); //*cp->ring.head = 0; cp->ring.tail = 0;}static void uninitRingBuffer( device_info *di ){ vuint8 *regs = di->regs; // abort any activity Radeon_ResetEngine( di ); // disable CP BM OUTREG( regs, RADEON_CP_CSQ_CNTL, RADEON_CSQ_PRIDIS_INDDIS ); // read-back for flushing INREG( regs, RADEON_CP_CSQ_CNTL ); FREE_MEM( mt_nonlocal, di->si->cp.ring.mem_handle );}static status_t initCPFeedback( device_info *di ){ CP_info *cp = &di->si->cp; vuint8 *regs = di->regs; int32 offset; memory_type_e memory_type; status_t res; // status information should be in PCI memory, so CPU can // poll it without locking the bus (PCI memory is the only // cachable memory available) memory_type = mt_PCI; ALLOC_MEM( RADEON_SCRATCH_REG_OFFSET + 0x40, memory_type, true, &cp->feedback.mem_handle, &offset ); if( res != B_OK ) { SHOW_ERROR0( 0, "Cannot allocate buffers for status information" ); return res; } // setup CP read pointer buffer cp->feedback.mem_type = memory_type; cp->feedback.head_mem_offset = offset; cp->feedback.head_vm_address = MEM2GC( memory_type, cp->feedback.head_mem_offset ); OUTREG( regs, RADEON_CP_RB_RPTR_ADDR, cp->feedback.head_vm_address ); SHOW_INFO( 3, "CP read pointer buffer==%lx", cp->feedback.head_vm_address ); // setup scratch register buffer cp->feedback.scratch_mem_offset = offset + RADEON_SCRATCH_REG_OFFSET; cp->feedback.scratch_vm_start = MEM2GC( memory_type, cp->feedback.scratch_mem_offset ); OUTREG( regs, RADEON_SCRATCH_ADDR, cp->feedback.scratch_vm_start ); OUTREG( regs, RADEON_SCRATCH_UMSK, 0x3f ); *(uint32 *)MEM2CPU( cp->feedback.mem_type, cp->feedback.head_mem_offset) = 0; memset( MEM2CPU( cp->feedback.mem_type, cp->feedback.scratch_mem_offset), 0, 0x40 ); //*cp->ring.head = 0;}static void uninitCPFeedback( device_info *di ){ vuint8 *regs = di->regs; // don't allow any scratch buffer update OUTREG( regs, RADEON_SCRATCH_UMSK, 0x0 ); FREE_MEM( mt_PCI, di->si->cp.feedback.mem_handle );}static status_t initIndirectBuffers( device_info *di ){ CP_info *cp = &di->si->cp; int32 offset; memory_type_e memory_type; int i; status_t res; memory_type = mt_nonlocal; ALLOC_MEM( NUM_INDIRECT_BUFFERS * INDIRECT_BUFFER_SIZE * 4, memory_type, true, &cp->buffers.mem_handle, &offset ); if( res != B_OK ) { SHOW_ERROR0( 0, "Cannot allocate indirect buffers" ); return B_ERROR; } cp->buffers.mem_type = memory_type; cp->buffers.mem_offset = offset; cp->buffers.vm_start = MEM2GC( memory_type, cp->buffers.mem_offset ); for( i = 0; i < NUM_INDIRECT_BUFFERS - 1; ++i ) { cp->buffers.buffers[i].next = i + 1; } cp->buffers.buffers[i].next = -1; cp->buffers.free_list = 0; cp->buffers.oldest = -1; cp->buffers.newest = -1; cp->buffers.active_state = -1; cp->buffers.cur_tag = 0; memset( MEM2CPU( cp->buffers.mem_type, cp->buffers.mem_offset), 0, NUM_INDIRECT_BUFFERS * INDIRECT_BUFFER_SIZE * 4 ); return B_OK;}static void uninitIndirectBuffers( device_info *di ){ FREE_MEM( mt_nonlocal, di->si->cp.buffers.mem_handle );}// initialize CP so it's ready for BMstatus_t Radeon_InitCP( device_info *di ){ thread_id thid; thread_info thinfo; status_t res; SHOW_FLOW0( 3, "" ); // this is _really_ necessary so functions like ResetEngine() know // that the CP is not set up yet memset( &di->si->cp, 0, sizeof( di->si->cp )); if( (res = INIT_BEN( di->si->cp.lock, "Radeon CP" )) < 0 ) return res; // HACK: change owner of benaphore semaphore to team of calling thread; // reason: user code cannot acquire kernel semaphores, but the accelerant // is in user space; interestingly, it's enough to change the semaphore's // owner to _any_ non-system team (that's the only security check done by // the kernel) thid = find_thread( NULL ); get_thread_info( thid, &thinfo ); set_sem_owner( di->si->cp.lock.sem, thinfo.team ); // init raw CP loadMicroEngineRAMData( di ); // do soft-reset Radeon_ResetEngine( di ); // after warm-reset, the CP may still be active and thus react to // register writes during initialization unpredictably, so we better // stop it first OUTREG( di->regs, RADEON_CP_CSQ_CNTL, RADEON_CSQ_PRIDIS_INDDIS ); INREG( di->regs, RADEON_CP_CSQ_CNTL ); // reset CP to make disabling active Radeon_ResetEngine( di ); res = initRingBuffer( di, CP_RING_SIZE ); if( res < 0 ) goto err4; res = initCPFeedback( di ); if( res < 0 ) goto err3; res = initIndirectBuffers( di ); if( res < 0 ) goto err2; // tell CP to use BM Radeon_WaitForIdle( di, false, false ); // enable direct and indirect CP bus mastering OUTREG( di->regs, RADEON_CP_CSQ_CNTL, RADEON_CSQ_PRIBM_INDBM ); // allow bus mastering in general OUTREGP( di->regs, RADEON_BUS_CNTL, 0, ~RADEON_BUS_MASTER_DIS ); // don't allow mixing of 2D/3D/scratch/wait_until commands // (in fact, this doesn't seem to make any difference as we do a // manual sync in all these cases anyway) OUTREG( di->regs, RADEON_ISYNC_CNTL, RADEON_ISYNC_ANY2D_IDLE3D | RADEON_ISYNC_ANY3D_IDLE2D | RADEON_ISYNC_WAIT_IDLEGUI | RADEON_ISYNC_CPSCRATCH_IDLEGUI ); SHOW_FLOW( 3, "bus_cntl=%lx", INREG( di->regs, RADEON_BUS_CNTL )); SHOW_FLOW0( 3, "Done" ); return B_OK; //err:// uninitIndirectBuffers( ai ); err2: uninitCPFeedback( di );err3: uninitRingBuffer( di );err4: DELETE_BEN( di->si->cp.lock ); return res;}// shutdown CP, freeing any memoryvoid Radeon_UninitCP( device_info *di ){ vuint8 *regs = di->regs; // abort any pending commands Radeon_ResetEngine( di ); // disable CP BM OUTREG( regs, RADEON_CP_CSQ_CNTL, RADEON_CSQ_PRIDIS_INDDIS ); // read-back for flushing INREG( regs, RADEON_CP_CSQ_CNTL ); uninitRingBuffer( di ); uninitCPFeedback( di ); uninitIndirectBuffers( di ); DELETE_BEN( di->si->cp.lock );}// mark all indirect buffers as being free;// this should only be called after a reset;// lock must be holdvoid Radeon_DiscardAllIndirectBuffers( device_info *di ){ CP_info *cp = &di->si->cp; // during init, there is no indirect buffer if( cp->buffers.mem_handle == 0 ) return; // mark all sent indirect buffers as free while( cp->buffers.oldest != -1 ) { indirect_buffer *oldest_buffer = &cp->buffers.buffers[cp->buffers.oldest]; int tmp_oldest_buffer; SHOW_FLOW( 0, "%d", cp->buffers.oldest ); // remove buffer from "used" list tmp_oldest_buffer = oldest_buffer->next; if( tmp_oldest_buffer == -1 ) cp->buffers.newest = -1; // put it on free list oldest_buffer->next = cp->buffers.free_list; cp->buffers.free_list = cp->buffers.oldest; cp->buffers.oldest = tmp_oldest_buffer; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -