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

📄 ram.c

📁 QNX ADS BSP code for i.MX27 chips
💻 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"struct ram_entry {	paddr_t		addr;	paddr_t		size;};struct avoid_entry {	paddr32_t	start;	paddr32_t	end;};static int					sysram_added;static paddr32_t			ws_early_next;static paddr32_t			temp_syspage = NULL_PADDR32;static struct avoid_entry	*avoid_list;static unsigned				avoid_list_size;static struct ram_entry		*ram_list;static unsigned				ram_list_size;#define TEMP_SYSPAGE_SIZE (ROUNDPG(KILO(32)))#define MAX_RAM_LIST_SIZE	KILO(3)#define MAX_AVOID_LIST_SIZE	KILO(1)static intadd_mem(paddr_t start, paddr_t size) {	paddr_t 			 e, s;	struct ram_entry	*r;	struct ram_entry	*ram = ram_list;	//kprintf( "add_mem(%L,%L)\n", (paddr64_t)start, (paddr64_t)size );	if(size > 0) {		for(r = ram; r->size != 0; r++) {			if(r->addr > start) break;		}		if(ram_list_size > (MAX_RAM_LIST_SIZE - sizeof(*r))) {			crash("RAM entry array overflow");		}		memmove(&r[1], r, ram_list_size - PTR_DIFF(r, ram));		ram_list_size += sizeof(*r);		r->addr = start;		r->size = size;		for(r = ram+1; r->size != 0; r++) {			e = r[-1].addr + r[-1].size;			s = r->addr;			if(s <= e) {				if((s + r->size) > e) e = s + r->size;				memmove(r, &r[1], ram_list_size - PTR_DIFF(&r[1], ram));				ram_list_size -= sizeof(*r);				--r;				r->size = e - r->addr;			}		}	}	return 0;}static intfix_size(paddr_t *sp, paddr_t *ep, paddr_t as, paddr_t ae) {	paddr_t		s = *sp;	paddr_t		e = *ep;	if(s >= ae) return 1;	if(e <= as) return 1;	if(s >= as) {		if(e <= ae) return 0;		*sp = ae;	} else if(e < ae) {		*ep = as;	} else if((as-s) > (e-ae)) {		*ep = as;	} else {		*sp = ae;	}	return 1;}paddr_tfind_top_ram(paddr_t size) {	struct ram_entry		*r;	struct avoid_entry		*a;	paddr_t 				s;	paddr_t 				e;	paddr_t					chk;	paddr_t					top = 0;	size = ROUND(size, lsp.system_private.p->pagesize);	for(r = ram_list; r->size != 0; r++) {		s = r->addr;		e = s + r->size;		for(a = avoid_list; a->end != 0; ++a) {			if(!fix_size(&s, &e, a->start, a->end)) goto next_one;		}		if((e-s) >= size) {			chk = e - size;			if(chk > top) top = chk;		}next_one: ;	}	if(top == 0) top = NULL_PADDR;	return top;}paddr32_tfind_ram(size_t size, unsigned align, unsigned colour, unsigned mask) {	struct ram_entry		*ram = ram_list;	struct ram_entry		*r;	paddr_t 				s;	paddr_t 				e;	paddr_t					addr;	struct avoid_entry		*a;	//NYI: should make sure memory comes out of the 1-to-1 mapping region	for(r = ram; r->size != 0; r++) {		s = r->addr;		e = s + r->size;		for(a = avoid_list; a->end != 0; ++a) {			if(!fix_size(&s, &e, a->start, a->end)) goto next_one;		}		addr = ROUND(s, align);		if((addr & mask) != colour) {			unsigned	incr;			incr = ((mask - 1) | mask) + 1;			addr = ((addr + incr) & ~mask) | colour;		}		if(addr >= e) continue;		if(size <= (e - addr)) return addr;next_one: ;	}	return NULL_PADDR32;}		paddr_talloc_ram(paddr_t addr, paddr_t size, unsigned align) {	struct ram_entry	*ram = ram_list;	struct ram_entry	*r;	paddr_t 			s, e, end;	//kprintf("alloc_ram(%L,%L,%l) => ", (paddr64_t)addr, (paddr64_t)size, align);	if(addr == NULL_PADDR) {		addr = find_ram(size, align, 0, 0);		if(addr == NULL_PADDR32) {//kprintf("NULL_PADDR\n");			return NULL_PADDR;		}	}//kprintf("%L\n", (paddr64_t)addr);	end = addr + size;	for(r = ram; r->size != 0; r++) {		s = r->addr;		e = s + r->size;		if((addr <= s && end > s)		|| (addr >= s && addr < e)		|| (end  >= s && end  < e)) {			if(end  > e) e=end;			if(addr < s) s=addr;			if(addr == s && end == e) {				memmove(r, &r[1], ram_list_size - PTR_DIFF(&r[1], ram));				ram_list_size -= sizeof(*r);				--r;			} else if(addr == s) {				r->size = e - end;				r->addr = end;			} else {				r->size = addr - s;				if(e != end) {					add_mem(end, e - end);				}			}		}	}	//	// If add_sysram() has been called, we need to adjust the start/end	// fields	//	if(sysram_added) {		unsigned			off;		struct asinfo_entry	*as;		--end;		off = AS_NULL_OFF;		for( ;; ) {			off = as_find_containing(off, addr, end, "sysram");			if(off == AS_NULL_OFF) break;			as = as_off2info(off);			s = as->start;			e = as->end;			if(end  > e) e=end;			if(addr < s) s=addr;			if(addr == s && end == e) {				crash("Can't remove whole sysram entry.\n");			} else if(addr == s) {				as->start = end + 1;			} else {				as->end = addr - 1;				if(e != end) {					as_add(end+1, e, AS_ATTR_RAM, "sysram", as->owner);				}			}		}	}	return addr;}paddr32_tcalloc_ram(size_t size, unsigned align) {	paddr32_t a;		a = alloc_ram(NULL_PADDR, size, align);	if(a != NULL_PADDR32) {		memset(MAKE_1TO1_PTR(a), 0, size);	}	return a;}voidadd_ram(paddr_t start, paddr_t size) {	if(lsp.asinfo.size == 0) {		init_asinfo(as_default());	}	as_add_containing(start, start + size - 1, AS_ATTR_RAM, "ram", "memory");	add_mem(start, size);	//Avoid using memory covered by image	alloc_ram(shdr->ram_paddr+shdr->startup_size,				shdr->ram_size-shdr->startup_size, 1);	//Avoid using memory reserved for the CPU (exception table)	#if defined(CPU_MEM_RESERVE_SIZE) && (CPU_MEM_RESERVE_SIZE > 0)	   alloc_ram(CPU_MEM_RESERVE_START, CPU_MEM_RESERVE_SIZE, 1);	#endif	//Get more space for the temporary system page we're building.	if(temp_syspage == NULL_PADDR32) {		temp_syspage = find_ram(TEMP_SYSPAGE_SIZE, __PAGESIZE, 0, 0);		if(temp_syspage != NULL_PADDR32) {			avoid_ram(temp_syspage, TEMP_SYSPAGE_SIZE);			reloc_syspage_memory(MAKE_1TO1_PTR(temp_syspage), TEMP_SYSPAGE_SIZE);		}	}}voidavoid_ram(paddr32_t start, size_t size) {	struct avoid_entry	*avoid;	avoid = (void *)((uint8_t *)avoid_list + avoid_list_size);	avoid[-1].start = start;	avoid[-1].end = start + size;	avoid[0].end = 0;	avoid_list_size += sizeof(*avoid);}//// Add all the "sysram" entries to the asinfo section. Note that we haven't// allocated the system page storage yet, so we're going to have adjust// the start/end fields when that happens.//voidadd_sysram() {	struct ram_entry	*ram;	for(ram = ram_list; ram->size != 0; ++ram) {		as_add_containing(ram->addr, ram->addr+ram->size-1,				AS_ATTR_RAM, "sysram", "ram");	}	sysram_added = 1;}voidws_init() {	// We can be fairly sure there's some ram following :-).	ws_early_next = ROUND(shdr->ram_paddr + shdr->ram_size, sizeof(uint64_t));	avoid_list = MAKE_1TO1_PTR(ws_early_next);	avoid_list[0].start = ws_early_next;	ws_early_next += ROUND(MAX_AVOID_LIST_SIZE, sizeof(uint64_t));	avoid_list[0].end = ws_early_next;	avoid_list[1].end = 0;	avoid_list_size = sizeof(avoid_list[0])*2;	ram_list = ws_alloc(MAX_RAM_LIST_SIZE);	ram_list->size = 0;	ram_list_size = sizeof(struct ram_entry);	//Avoid using memory covered by startup	avoid_ram(shdr->ram_paddr, shdr->startup_size);#ifdef CPU_MEM_AVOID_START	//Avoid using memory that might have something interesting	avoid_ram(CPU_MEM_AVOID_START, CPU_MEM_AVOID_SIZE);#endif}void *ws_alloc(size_t size) {	paddr32_t	paddr;	size = ROUND(size, sizeof(uint64_t));	if(ram_list_size <= sizeof(struct ram_entry)) {		// no add_ram()'s have been done yet.		paddr = ws_early_next;		ws_early_next += size;	} else {		// we've been told where memory is.		paddr = find_ram(size, sizeof(uint64_t), 0, 0);		if(paddr == NULL_PADDR32) {			return(NULL);		}	}	avoid_ram(paddr, size);	return(MAKE_1TO1_PTR(paddr));}

⌨️ 快捷键说明

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