⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ppcv_map_600.c

📁 qnx powerpc MPC8245的 BSP源文件
💻 C
字号:
/* * $QNXLicenseC:  * Copyright 2007, QNX Software Systems.   *   * Licensed under the Apache License, Version 2.0 (the "License"). You   * may not reproduce, modify or distribute this software except in   * compliance with the License. You may obtain a copy of the License   * at: http://www.apache.org/licenses/LICENSE-2.0   *   * Unless required by applicable law or agreed to in writing, software   * distributed under the License is distributed on an "AS IS" basis,   * WITHOUT WARRANTIES OF ANY KIND, either express or implied.  *  * This file may contain contributions from others, either as   * contributors under the License or as licensors under other terms.    * Please review this entire file for other proprietary rights or license   * notices, as well as the QNX Development Suite License Guide at   * http://licensing.qnx.com/license-guide/ for other information.  * $  */#include "startup.h"#define FIRST_VADDR	(GIG(1) - MEG(256))#define NUM_BATS	4struct bat_info {		uintptr_t		vaddr;		paddr32_t		paddr;		unsigned		size;		unsigned short	flags;		unsigned short	ref;};// Can't use PROT_CALLOUT because it's too big to fit in 'flags' field#define MYCALLOUT_FLAG		1static struct bat_info	bat[NUM_BATS] = {	{ 0, 0, MEG(256), PROT_READ|PROT_WRITE, 1} // initial 1-1 mapping area};static voidinvalidate_device_bats() {	set_spr(PPC_SPR_IBAT1U, 0);	set_spr(PPC_SPR_IBAT2U, 0);	set_spr(PPC_SPR_IBAT3U, 0);	set_spr(PPC_SPR_DBAT1U, 0);	set_spr(PPC_SPR_DBAT2U, 0);	set_spr(PPC_SPR_DBAT3U, 0);	ppc_isync();}#define BAT_FLAG_VALID	0x01#define BAT_FLAG_CFG2	0x02static voidload_bat(unsigned bi, unsigned ti, int flags) {	unsigned		up;	unsigned		lo;	struct bat_info	*bp;	bp = &bat[ti];	up = bp->vaddr & PPC_BATU_BEPI_MASK;	if(flags & BAT_FLAG_VALID) {		up |= PPC_BATU_VS;		if(bp->flags & PROT_USER) up |= PPC_BATU_VP;	}	up |= ((bp->size-1) >> (29-14)) & PPC_BATU_BL_MASK;	lo = (bp->paddr & PPC_BATL_BRPN_MASK) | PPC_BATL_PP_RW;	if(bp->flags & PROT_NOCACHE) {		lo |= PPC_BATL_I | PPC_BATL_G;	} else {		lo |= PPC_BATL_M;		// If we're not transfering to the bootstraps, we want a		// write-through cache for consistency in an SMP system		if(!(flags & BAT_FLAG_CFG2)) lo |= PPC_BATL_W;	}	set_spr_indirect(PPC_SPR_IBAT0L + (bi*2), lo & ~(PPC_BATL_G|PPC_BATL_W));	set_spr_indirect(PPC_SPR_IBAT0U + (bi*2), up);	set_spr_indirect(PPC_SPR_DBAT0L + (bi*2), lo);	set_spr_indirect(PPC_SPR_DBAT0U + (bi*2), up);	ppc_isync(); ppc_sync();}		voidppcv_mmuconfig1_600(int cpu) {	unsigned	i;	// Invalidate BATs	set_spr(PPC_SPR_IBAT0U, 0);	set_spr(PPC_SPR_DBAT0U, 0);	invalidate_device_bats();	// clear segment registers	for(i = 0; i < 16; i++) {		set_sreg(i << 28, 0);	}	//Invalidate the TLB's	for(i = 0; i < _ONEBIT32B(19); i+= _ONEBIT32B(14)) {		asm volatile ( "tlbie %0; eieio; tlbsync;"::"b"(i));	}	// Set a 1-1 translation map, so we can do non-cached accesses later.	// Load any device mappings (for SMP on non-bootstrap CPU's).	for(i = 0; i < NUM_BATS; ++i) {		if(bat[i].ref != 0) {			load_bat(0, 0, BAT_FLAG_VALID);		}	}	set_msr(get_msr() | (PPC_MSR_IR|PPC_MSR_DR));	ppc_isync();	ppc_sync();}voidppcv_mmuconfig2_600(int cpu) {	unsigned	i;	unsigned	j;	// compress the bats	invalidate_device_bats();	for(i = 1, j = 1; i < NUM_BATS; ++i) {		if(bat[i].flags & MYCALLOUT_FLAG) {			load_bat(j++, i, BAT_FLAG_CFG2|BAT_FLAG_VALID);		}	}	set_spr(PPC_SPR_DBAT0L, get_spr(PPC_SPR_DBAT0L) & ~PPC_BATL_W);	ppc_isync();}void *ppcv_map_600(unsigned size, paddr_t phys, unsigned prot_flags) {	unsigned		i;	struct bat_info	*bp;	uintptr_t		free_vaddr = FIRST_VADDR;	int				free_bat = -1;	i = 0;	for(;;) {		if(i >= NUM_BATS) {			if(free_bat >= 0) break;			return NULL;		}		bp = &bat[i];		if(bp->ref != 0) {			if((phys >= bp->paddr) && ((phys+size-1) < (bp->paddr+bp->size-1))) {				if((prot_flags & PROT_NOCACHE) == (bp->flags & PROT_NOCACHE)) {					// can reuse this entry					goto reuse_one;				}			}			if(free_vaddr < (bp->vaddr + bp->size)) {				free_vaddr = bp->vaddr + bp->size;			}		} else {			free_bat = i;		}		++i;	}	//set up a new bat	#define BAT_SIZE	MEG(64)	bp = &bat[free_bat];	bp->vaddr = free_vaddr & ~(BAT_SIZE-1);	bp->paddr = phys & ~(BAT_SIZE-1);	bp->size = BAT_SIZE;	bp->flags = prot_flags;	load_bat(free_bat, free_bat, BAT_FLAG_VALID);reuse_one:	bp->ref++;	if(prot_flags & PROT_CALLOUT) {		bp->ref++; 	// so it never gets released		bp->flags |= MYCALLOUT_FLAG;	}	return (void *)(bp->vaddr + (uintptr_t)(phys - bp->paddr));}voidppcv_unmap_600(void *p) {	uintptr_t		vaddr = (uintptr_t)p;	unsigned		i;	struct bat_info	*bp;	for(i = 0; i < NUM_BATS; ++i) {		bp = &bat[i];		if(bp->ref != 0) {			if((vaddr >= bp->vaddr) && (vaddr <= (bp->vaddr+bp->size-1))) {				if(--bp->ref == 0) {					load_bat(i, i, 0);				}				break;			}		}	}}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -