📄 sys.c
字号:
last = addr + (count - size); if( last < addr ) return SHELL_ERROR_OVERFLOW; SYSCON_read( SYSCON_CPU_TLB_AVAIL_ID, (void *)&sys_mmu_tlb, sizeof( bool ) ); if( KUSEG( addr ) == addr ) range_start = R_KUSEG; else if( KSEG0( addr ) == addr ) range_start = R_KSEG0; else if( KSEG1( addr ) == addr ) range_start = R_KSEG1; else if( KSSEG( addr ) == addr ) range_start = R_KSSEG; else range_start = R_KSEG3; switch( range_start ) { case R_KUSEG : case R_KSSEG : case R_KSEG3 : if( !sys_mmu_tlb ) { /* Assume Fixed Mapping MMU */ /* Determine ERL setting */ SYSCON_read( SYSCON_CPU_CP0_STATUS_ID, (void *)&erl, sizeof(UINT32) ); erl &= M_StatusERL; if( last < KSEG0BASE ) { /* Range contained within KUSEG */ if( !erl ) { addr += 0x40000000; last += 0x40000000; } return sys_validate_ram_range( addr, last ); } else if( addr >= KSSEGBASE ) { /* Range contained within KSSEG,KSEG3 */ return sys_validate_ram_range( addr, last ); } else { /* Range overflows KUSEG */ rc = sys_validate_ram_range( erl ? addr : addr + 0x40000000, erl ? KSEG0BASE- size : KSEG0BASE - size + 0x40000000 ); return ( rc != OK ) ? rc : /* Continue in KSEG0 */ sys_validate_range( KSEG0BASE, count - (KSEG0BASE - addr), size, write ); } } else { /* MMU = TLB */ switch( sys_tlb_lookup( addr, &phys, &pagesize ) ) { case SYS_TLB_WP : if( write ) { sprintf( msg, "Address = 0x%08x", addr ); shell_error_data = msg; return SHELL_ERROR_TLB_WP; } /* Fallthrough !! */ case SYS_TLB_OK : rc = sys_validate_ram_range( phys, phys + pagesize - size ); if( rc != OK ) return rc; addr += pagesize; return ( addr > last ) ? OK : sys_validate_range( addr, count - pagesize, size, write ); break; case SYS_TLB_NOTFOUND : case SYS_TLB_NOTVALID : default : /* Should not happen */ sprintf( msg, "Address = 0x%08x", addr ); shell_error_data = msg; return SHELL_ERROR_TLB; } } break; case R_KSEG0 : if( KSEG0( last ) == last ) { /* Range contained within KSEG0 */ return sys_validate_ram_range( PHYS(addr), PHYS(last) ); } else { /* Range overflows KSEG0 */ rc = sys_validate_ram_range( PHYS(addr), PHYS(KSEG1BASE-size) ); return ( rc != OK ) ? rc : /* Continue in KSEG1 */ sys_validate_range( KSEG1BASE, count - (KSEG1BASE - addr), size, write ); } break; case R_KSEG1 : if( KSEG1( last ) == last ) { /* Range contained within KSEG1 */ return sys_validate_ram_range( PHYS(addr), PHYS(last) ); } else { /* Range overflows KSEG1 */ rc = sys_validate_ram_range( PHYS(addr), PHYS(KSSEGBASE-size) ); return ( rc != OK ) ? rc : /* Continue in KSSEG */ sys_validate_range( KSSEGBASE, count - (KSSEGBASE - addr), size, write ); } break; } return OK; /* Should never reach this point */}/************************************************************************ * * sys_kseg0 * Description : * ------------- * * Determine KSEG0 address corresponding to input address. * * In case input address is TLB mapped, a lookup is performed in the * TLB to determine the physical address. Then, the corresponding * KSEG0 address is calculated. * * In case input address is in KSEG1 range, it is converted to KSEG0. * * In case of fixed mapping TLB, a KUSEG address is mapped to a * corresponding KSEG0 address based on the ERL setting. * * Return values : * --------------- * * TRUE if conversion was successfull, otherwise FALSE * ************************************************************************/boolsys_kseg0( UINT32 addr, /* Address to be converted */ UINT32 *kseg0addr ) /* OUT : Converted address */{ UINT32 phys, pagesize; bool sys_mmu_tlb; UINT32 erl; SYSCON_read( SYSCON_CPU_TLB_AVAIL_ID, (void *)&sys_mmu_tlb, sizeof( bool ) ); if( sys_mmu_tlb ) { /* MMU = TLB */ if( (KSEG0( addr ) == addr) || (KSEG1( addr ) == addr) ) { *kseg0addr = KSEG0(addr); return TRUE; } else { if( sys_tlb_lookup( addr, &phys, &pagesize ) == SYS_TLB_OK ) { *kseg0addr = KSEG0( phys ); return TRUE; } else return FALSE; } } else { /* Assume Fixed Mapping MMU */ if( KUSEG( addr ) == addr ) { /* Determine ERL setting */ SYSCON_read( SYSCON_CPU_CP0_STATUS_ID, (void *)&erl, sizeof(UINT32) ); if( (erl & M_StatusERL) == 0 ) return FALSE; /* Can't be mapped to KSEG0 */ if( (addr & KSEG_MSK) != addr ) return FALSE; /* Can't be mapped to KSEG0 */ *kseg0addr = KSEG0(addr); return TRUE; } else if( KSEG0( addr ) == addr ) { *kseg0addr = addr; return TRUE; } else if( KSEG1( addr ) == addr ) { *kseg0addr = KSEG0(addr); return TRUE; } else { /* KSSEG/KSEG3, can't be mapped to KSEG0 */ return FALSE; } }}/************************************************************************ * * sys_legal_align * Description : * ------------- * * Determine if alignment of address is legal * * Return values : * --------------- * * TRUE -> Legal alignment, FALSE -> Illegal alignment * ************************************************************************/boolsys_legal_align( UINT32 address, UINT32 align ){ return (address == (address & ~(align - 1))) ? TRUE : FALSE;}/************************************************************************ * Implementation : static functions ************************************************************************//************************************************************************ * determine_dev ************************************************************************/static booldetermine_dev( UINT32 port, UINT32 *major, UINT32 *minor ){ UINT32 id_major, id_minor; if( port == PORT_TTY0 ) { id_major = SYSCON_COM_TTY0_MAJOR; id_minor = SYSCON_COM_TTY0_MINOR; } else if( port == PORT_TTY1 ) { id_major = SYSCON_COM_TTY1_MAJOR; id_minor = SYSCON_COM_TTY1_MINOR; } else return FALSE; SYSCON_read( id_major, (void *)(major), sizeof(UINT32) ); SYSCON_read( id_minor, (void *)(minor), sizeof(UINT32) ); return TRUE;}/************************************************************************ * * sys_validate_ram_range * Description : * ------------- * * Perform range check relating to RAM use. * * The range defined by parameters 'start' and 'last' is checked with * relation to RAM use. * * The memory map allocates a range for RAM. In case the RAM * module does not occupy this entire range, there will be an * "empty" RAM range. We detect whether the specified range * hits this empty RAM range. If so, we return an error code. * Otherwise, OK is returned. * * In case of a hit in the unused range, shell_err_data is set to a * text string stating the illegal address. This may be used by * error handling. * * Return values : * --------------- * * OK : No error * SHELL_ERROR_RAM_RANGE : Error detected * ************************************************************************/static UINT32sys_validate_ram_range( UINT32 start, /* Start address (physical) */ UINT32 last ) /* Last address (physical) */{ static void *ram_base; static UINT32 ram_actual_size, ram_size; static UINT32 ram_range_unused_start; static UINT32 ram_range_unused_last; static bool first = TRUE; if( first ) { /* Self-initialisation */ first = FALSE; SYSCON_read( SYSCON_BOARD_SYSTEMRAM_ACTUAL_SIZE_ID, (void *)&ram_actual_size, sizeof(UINT32) ); SYSCON_read( SYSCON_BOARD_SYSTEMRAM_BASE_ID, (void *)&ram_base, sizeof(void *) ); SYSCON_read( SYSCON_BOARD_SYSTEMRAM_SIZE_ID, (void *)&ram_size, sizeof(UINT32) ); ram_range_unused_start = (UINT32)ram_base + ram_actual_size; ram_range_unused_last = (UINT32)ram_base + ram_size - 1; } if( ram_actual_size == ram_size ) return OK; /* No unused RAM space */ if( start <= ram_range_unused_last ) { if( start >= ram_range_unused_start ) { sprintf( msg, "Address = 0x%08x", start ); shell_error_data = msg; return SHELL_ERROR_RAM_RANGE; } if( last >= ram_range_unused_start ) { sprintf( msg, "Address = 0x%08x", ram_range_unused_start ); shell_error_data = msg; return SHELL_ERROR_RAM_RANGE; } } return OK;}/************************************************************************ * * sys_func_noram * Description : * ------------- * * Access function while executing from flash. * All RAM access will be disabled while accessing function. * * Return values : * --------------- * * UINT32 returned by requested function * ************************************************************************/UINT32sys_func_noram( t_sys_func_noram func, UINT32 parm1, UINT32 parm2, UINT32 parm3 ){ UINT32 old_ie; UINT32 rc; /* Disable interrupts */ old_ie = sys_disable_int(); /* Stop DMA */ sys_dma_enable( FALSE ); /* Call function */ rc = (*func)(parm1, parm2, parm3); /* Restart DMA */ sys_dma_enable( TRUE ); /* Restore interrupt enable setting */ if(old_ie) sys_enable_int(); return rc;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -