prom.c

来自「最新版的u-boot,2008-10-18发布」· C语言 代码 · 共 1,048 行 · 第 1/2 页

C
1,048
字号
	 M_LEON2 | M_LEON2_SOC,	/* machine type */	 {0, 0, 0, 0, 0, 0},	/* eth */	 0,			/* date */	 0,			/* sernum */	 0,			/* checksum */	 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}	/* reserved */	 },	{	 __va(no_nextnode),	 __va(no_child),	 __va(no_proplen),	 __va(no_getprop),	 __va(no_setprop),	 __va(no_nextprop)	 },	__va(&spi.totphys),	{	 NULL,	 (char *)CFG_SDRAM_BASE,	 0,	 },	__va(&spi.avail),	{	 NULL,	 (char *)CFG_SDRAM_BASE,	 0,	 },	NULL,			/* prommap_p */	NULL,	__va(&spi.bootargs),	{	 {NULL, __va(spi.arg), NULL /*... */ },	 /*... */	 },	{	 0,	 0,			/* sun4c v0 prom */	 0, 0,	 {__va(&spi.totphys_p), __va(&spi.prommap_p), __va(&spi.avail_p)},	 __va(&spi.nodeops),	 NULL, {NULL /* ... */ },	 NULL, NULL,	 NULL, NULL,		/* pv_getchar, pv_putchar */	 __va(leon_nbgetchar), __va(leon_nbputchar),	 NULL,	 __va(leon_reboot),	 NULL,	 NULL,	 NULL,	 __va(leon_halt),	 __va(&spi.synchook),	 {NULL},	 __va(&spi.bootargs_p)	 /*... */	 },	{	 {0, __va(spi.root_properties + 3) /* NULL, NULL, -1 */ },	 {0, __va(spi.root_properties)},	 /* cpu 0, must be spi.nodes[2] see leon_prom_init() */	 {1, __va(spi.cpu_properties)},#undef  CPUENTRY#define CPUENTRY(idx) \	  {1, __va(spi.cpu_properties##idx) }	/* cpu <idx> */	 CPUENTRY(1),	 CPUENTRY(2),	 CPUENTRY(3),	 CPUENTRY(4),	 CPUENTRY(5),	 CPUENTRY(6),	 CPUENTRY(7),	 CPUENTRY(8),	 CPUENTRY(9),	 CPUENTRY(10),	 CPUENTRY(11),	 CPUENTRY(12),	 CPUENTRY(13),	 CPUENTRY(14),	 CPUENTRY(15),	 CPUENTRY(16),	 CPUENTRY(17),	 CPUENTRY(18),	 CPUENTRY(19),	 CPUENTRY(20),	 CPUENTRY(21),	 CPUENTRY(22),	 CPUENTRY(23),	 CPUENTRY(24),	 CPUENTRY(25),	 CPUENTRY(26),	 CPUENTRY(27),	 CPUENTRY(28),	 CPUENTRY(29),	 CPUENTRY(30),	 CPUENTRY(31),	 {-1, __va(spi.root_properties + 3) /* NULL, NULL, -1 */ }	 },	"device_type",	"cpu",	"mid",	"idprom",	"compatability",	"leon2",	"mmu-nctx",	"clock-frequency",	"uart1_baud",	"uart2_baud",	CONFIG_DEFAULT_KERNEL_COMMAND_LINE};/* from arch/sparc/kernel/setup.c */#define RAMDISK_LOAD_FLAG 0x4000extern unsigned short root_flags;extern unsigned short root_dev;extern unsigned short ram_flags;extern unsigned int sparc_ramdisk_image;extern unsigned int sparc_ramdisk_size;extern int root_mountflags;extern char initrd_end, initrd_start;/* Reboot the CPU = jump to beginning of flash again. * * Make sure that all function are inlined here. */static void PROM_TEXT leon_reboot(char *bcommand){	register char *arg = bcommand;	void __attribute__ ((noreturn)) (*reboot_physical) (char *cmd);	/* get physical address */	struct leon_prom_info *pspi =	    (void *)(CFG_PROM_OFFSET + sizeof(srmmu_tables));	unsigned int *srmmu_ctx_table;	/* Turn of Interrupts */	set_pil(0xf);	/* Set kernel's context, context zero */	srmmu_set_context(0);	/* Get physical address of the MMU shutdown routine */	reboot_physical = (void *)	    SPARC_BYPASS_READ(&pspi->reloc_funcs.reboot_physical);	/* Now that we know the physical address of the function	 * we can make the MMU allow jumping to it.	 */	srmmu_ctx_table = (unsigned int *)srmmu_get_ctable_ptr();	srmmu_ctx_table = (unsigned int *)SPARC_BYPASS_READ(srmmu_ctx_table);	/* get physical address of kernel's context table (assume ptd) */	srmmu_ctx_table = (unsigned int *)	    (((unsigned int)srmmu_ctx_table & 0xfffffffc) << 4);	/* enable access to physical address of MMU shutdown function */	SPARC_BYPASS_WRITE(&srmmu_ctx_table			   [((unsigned int)reboot_physical) >> 24],			   (((unsigned int)reboot_physical & 0xff000000) >> 4) |			   0x1e);	/* flush TLB cache */	leon_flush_tlb_all();	/* flash instruction & data cache */	sparc_icache_flush_all();	sparc_dcache_flush_all();	/* jump to physical address function	 * so that when the MMU is disabled	 * we can continue to execute	 */	reboot_physical(arg);}static void PROM_TEXT leon_reboot_physical(char *bcommand){	void __attribute__ ((noreturn)) (*reset) (void);	/* Turn off MMU */	srmmu_set_mmureg(0);	/* Hardcoded start address */	reset = CFG_MONITOR_BASE;	/* flush data cache */	sparc_dcache_flush_all();	/* flush instruction cache */	sparc_icache_flush_all();	/* Jump to start in Flash */	reset();}static void PROM_TEXT leon_halt(void){	while (1) ;}/* get single char, don't care for blocking*/static int PROM_TEXT leon_nbgetchar(void){	return -1;}/* put single char, don't care for blocking*/static int PROM_TEXT leon_nbputchar(int c){	LEON2_regs *leon2 = (LEON2_regs *) LEON2_PREGS;	/***** put char in buffer... ***********	 * Make sure all functions are inline! *	 ***************************************/	/* Wait for last character to go. */	while (!(SPARC_BYPASS_READ(&leon2->UART_Status_1)		 & LEON2_UART_STAT_THE)) ;	/* Send data */	SPARC_BYPASS_WRITE(&leon2->UART_Channel_1, c);	/* Wait for data to be sent */	while (!(SPARC_BYPASS_READ(&leon2->UART_Status_1)		 & LEON2_UART_STAT_TSE)) ;	return 0;}/* node ops *//*#define nodes ((struct node *)__va(&pspi->nodes))*/#define nodes ((struct node *)(pspi->nodes))static int PROM_TEXT no_nextnode(int node){	/* get physical address */	struct leon_prom_info *pspi =	    (void *)(CFG_PROM_OFFSET + sizeof(srmmu_tables));	/* convert into virtual address */	pspi = (struct leon_prom_info *)	    (((unsigned int)pspi & 0x0fffffff) | PAGE_OFFSET);	if (nodes[node].level == nodes[node + 1].level)		return node + 1;	return -1;}static int PROM_TEXT no_child(int node){	/* get physical address */	struct leon_prom_info *pspi = (struct leon_prom_info *)	    (CFG_PROM_OFFSET + sizeof(srmmu_tables));	/* convert into virtual address */	pspi = (struct leon_prom_info *)	    (((unsigned int)pspi & 0x0fffffff) | PAGE_OFFSET);	if (nodes[node].level == nodes[node + 1].level - 1)		return node + 1;	return -1;}static struct property PROM_TEXT *find_property(int node, char *name){	/* get physical address */	struct leon_prom_info *pspi = (struct leon_prom_info *)	    (CFG_PROM_OFFSET + sizeof(srmmu_tables));	/* convert into virtual address */	pspi = (struct leon_prom_info *)	    (((unsigned int)pspi & 0x0fffffff) | PAGE_OFFSET);	struct property *prop = &nodes[node].properties[0];	while (prop && prop->name) {		if (pspi->reloc_funcs.strcmp(prop->name, name) == 0)			return prop;		prop++;	}	return NULL;}static int PROM_TEXT no_proplen(int node, char *name){	/* get physical address */	struct leon_prom_info *pspi = (struct leon_prom_info *)	    (CFG_PROM_OFFSET + sizeof(srmmu_tables));	/* convert into virtual address */	pspi = (struct leon_prom_info *)	    (((unsigned int)pspi & 0x0fffffff) | PAGE_OFFSET);	struct property *prop = pspi->reloc_funcs.find_property(node, name);	if (prop)		return prop->length;	return -1;}static int PROM_TEXT no_getprop(int node, char *name, char *value){	/* get physical address */	struct leon_prom_info *pspi = (struct leon_prom_info *)	    (CFG_PROM_OFFSET + sizeof(srmmu_tables));	/* convert into virtual address */	pspi = (struct leon_prom_info *)	    (((unsigned int)pspi & 0x0fffffff) | PAGE_OFFSET);	struct property *prop = pspi->reloc_funcs.find_property(node, name);	if (prop) {		pspi->reloc_funcs.memcpy(value, prop->value, prop->length);		return 1;	}	return -1;}static int PROM_TEXT no_setprop(int node, char *name, char *value, int len){	return -1;}static char PROM_TEXT *no_nextprop(int node, char *name){	/* get physical address */	struct leon_prom_info *pspi = (struct leon_prom_info *)	    (CFG_PROM_OFFSET + sizeof(srmmu_tables));	struct property *prop;	/* convert into virtual address */	pspi = (struct leon_prom_info *)	    (((unsigned int)pspi & 0x0fffffff) | PAGE_OFFSET);	if (!name || !name[0])		return nodes[node].properties[0].name;	prop = pspi->reloc_funcs.find_property(node, name);	if (prop)		return prop[1].name;	return NULL;}static int PROM_TEXT leon_strcmp(const char *s1, const char *s2){	register char result;	while (1) {		result = *s1 - *s2;		if (result || !*s1)			break;		s2++;		s1++;	}	return result;}static void *PROM_TEXT leon_memcpy(void *dest, const void *src, size_t n){	char *dst = (char *)dest, *source = (char *)src;	while (n--) {		*dst = *source;		dst++;		source++;	}	return dest;}#define GETREGSP(sp) __asm__ __volatile__("mov %%sp, %0" : "=r" (sp))void leon_prom_init(struct leon_prom_info *pspi){	unsigned long i;	unsigned char cksum, *ptr;	char *addr_str, *end;	unsigned long sp;	GETREGSP(sp);	pspi->freq_khz = CONFIG_SYS_CLK_FREQ / 1000;	/* Set Available main memory size */	pspi->totphys.num_bytes = CFG_PROM_OFFSET - CFG_SDRAM_BASE;	pspi->avail.num_bytes = pspi->totphys.num_bytes;#undef nodes	pspi->nodes[3].level = -1;	pspi->nodes[3].properties = __va(spi.root_properties + 3);	/* Set Ethernet MAC address from environment */	if ((addr_str = getenv("ethaddr")) != NULL) {		for (i = 0; i < 6; i++) {			pspi->idprom.id_ethaddr[i] = addr_str ?			    simple_strtoul(addr_str, &end, 16) : 0;			if (addr_str) {				addr_str = (*end) ? end + 1 : end;			}		}	} else {		/* HW Address not found in environment,		 * Set default HW address		 */		pspi->idprom.id_ethaddr[0] = 0;		pspi->idprom.id_ethaddr[1] = 0;		pspi->idprom.id_ethaddr[2] = 0;		pspi->idprom.id_ethaddr[3] = 0;		pspi->idprom.id_ethaddr[4] = 0;		pspi->idprom.id_ethaddr[5] = 0;	}	ptr = (unsigned char *)&pspi->idprom;	for (i = cksum = 0; i <= 0x0E; i++)		cksum ^= *ptr++;	pspi->idprom.id_cksum = cksum;}static inline void set_cache(unsigned long regval){	asm volatile ("sta %0, [%%g0] %1\n\t":: "r" (regval), "i"(2):"memory");}extern unsigned short bss_start, bss_end;/* mark as section .img.main.text, to be referenced in linker script */int prom_init(void){	struct leon_prom_info *pspi = (void *)	    ((((unsigned int)&spi) & PROM_SIZE_MASK) + CFG_PROM_OFFSET);	/* disable mmu */	srmmu_set_mmureg(0x00000000);	__asm__ __volatile__("flush\n\t");	/* init prom info struct */	leon_prom_init(pspi);	kernel_arg_promvec = &pspi->romvec;#ifdef PRINT_ROM_VEC	printf("Kernel rom vec: 0x%lx\n", (unsigned int)(&pspi->romvec));#endif	return 0;}/* Copy current kernel boot argument to ROMvec */void prepare_bootargs(char *bootargs){	struct leon_prom_info *pspi;	char *src, *dst;	int left;	/* if no bootargs set, skip copying ==> default bootline */	if (bootargs && (*bootargs != '\0')) {		pspi = (void *)((((unsigned int)&spi) & PROM_SIZE_MASK) +				CFG_PROM_OFFSET);		src = bootargs;		dst = &pspi->arg[0];		left = 255;	/* max len */		while (*src && left > 0) {			*dst++ = *src++;			left--;		}		/* terminate kernel command line string */		*dst = 0;	}}void srmmu_init_cpu(unsigned int entry){	sparc_srmmu_setup *psrmmu_tables = (void *)	    ((((unsigned int)&srmmu_tables) & PROM_SIZE_MASK) +	     CFG_PROM_OFFSET);	/* Make context 0 (kernel's context) point	 * to our prepared memory mapping	 */#define PTD 1	psrmmu_tables->ctx_table[0] =	    ((unsigned int)&psrmmu_tables->pgd_table[0x00]) >> 4 | PTD;	/* Set virtual kernel address 0xf0000000	 * to SRAM/SDRAM address.	 * Make it READ/WRITE/EXEC to SuperUser	 */#define PTE 2#define ACC_SU_ALL 0x1c	psrmmu_tables->pgd_table[0xf0] =	    (CFG_SDRAM_BASE >> 4) | ACC_SU_ALL | PTE;	psrmmu_tables->pgd_table[0xf1] =	    ((CFG_SDRAM_BASE + 0x1000000) >> 4) | ACC_SU_ALL | PTE;	psrmmu_tables->pgd_table[0xf2] =	    ((CFG_SDRAM_BASE + 0x2000000) >> 4) | ACC_SU_ALL | PTE;	psrmmu_tables->pgd_table[0xf3] =	    ((CFG_SDRAM_BASE + 0x3000000) >> 4) | ACC_SU_ALL | PTE;	psrmmu_tables->pgd_table[0xf4] =	    ((CFG_SDRAM_BASE + 0x4000000) >> 4) | ACC_SU_ALL | PTE;	psrmmu_tables->pgd_table[0xf5] =	    ((CFG_SDRAM_BASE + 0x5000000) >> 4) | ACC_SU_ALL | PTE;	psrmmu_tables->pgd_table[0xf6] =	    ((CFG_SDRAM_BASE + 0x6000000) >> 4) | ACC_SU_ALL | PTE;	psrmmu_tables->pgd_table[0xf7] =	    ((CFG_SDRAM_BASE + 0x7000000) >> 4) | ACC_SU_ALL | PTE;	/* convert rom vec pointer to virtual address */	kernel_arg_promvec = (struct linux_romvec *)	    (((unsigned int)kernel_arg_promvec & 0x0fffffff) | 0xf0000000);	/* Set Context pointer to point to context table	 * 256 contexts supported.	 */	srmmu_set_ctable_ptr((unsigned int)&psrmmu_tables->ctx_table[0]);	/* Set kernel's context, context zero */	srmmu_set_context(0);	/* Invalidate all Cache */	__asm__ __volatile__("flush\n\t");	srmmu_set_mmureg(0x00000001);	leon_flush_tlb_all();	leon_flush_cache_all();}

⌨️ 快捷键说明

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