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

📄 tgt_machdep.c

📁 MIPS处理器的bootloader,龙芯就是用的修改过的PMON2
💻 C
字号:
/*	$Id: tgt_machdep.c,v 1.5 2002/11/16 18:01:35 pefo Exp $ *//* * Copyright (c) 2000 Opsycon AB  (www.opsycon.se) * Copyright (c) 2000 Rtmx, Inc   (www.rtmx.com) *  * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed for Rtmx, Inc by *	Opsycon Open System Consulting AB, Sweden. * 4. The name of the author may not be used to endorse or promote products *    derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */#include <sys/types.h>#include <stdio.h>#include <setjmp.h>#include <termio.h>#include <string.h>#include <time.h>#include <sys/device.h>#include <dev/pci/pcivar.h>#include <machine/cpu.h>#include <machine/pio.h>#include <machine/asm.h>#include <machine/inline_asm.h>#include <autoconf.h>#include "pflash.h"#include "dev/pflash_tgt.h"#include "target/power7e.h"#include <pmon.h>#include <pmon/dev/ns16550.h>extern unsigned char hwethadr[6];static int md_pipefreq = 0;static int md_cpufreq = 0;static int clk_invalid = 0;static int nvram_invalid = 0;ConfigEntry	ConfigTable[] ={	{ (char *)COM1_BASE_ADDR, 0, ns16550, 256, B9600, NS16550HZ},	{ (char *)COM2_BASE_ADDR, 0, ns16550, 256, B9600, NS16550HZ},	{ 0 }};unsigned long _filebase;static void _probe_frequencies __P((void));static int cksum __P((void *, size_t, int));/* *  This function makes inital HW setup for debugger and *  returns the apropriate setting for the status register. */register_ttgt_enable(int machtype){	/* XXX Do any HW specific setup */	return(PSL_IR|PSL_DR|PSL_FP|PSL_RI|PSL_ME|PSL_FE_DFLT);}/* *  Target dependent version printout. *  Printout available target version information. */voidtgt_cmd_vers(){}voidtgt_logo(){}voidtgt_rtinit(){}static void_probe_frequencies(){static char pllratio[16] =	/* 0   1   2   3   4   5    6   7   8   9  10  11  12  13  14  15 *//*750***{  0, 75, 70,  1, 20, 65, 100, 45, 30, 55, 40, 50, 80, 60, 35, 0 };*//*7400*/{ 90, 75, 70,  1, 20, 65,  25, 45, 30, 55, 40, 50, 80, 60, 35, 0 };	int i;        int clkbase = M48T37_BASE + 8;	SBD_DISPLAY ("FREQ", CHKPNT_FREQ);	md_pipefreq = 400000000;	/* Defaults */	md_cpufreq = 66666667;	/*	 *  Check if clock is stopped and start it if it is.	 */	if(inb(clkbase + 1) & 0x80) {		outb(clkbase + 1, inb(clkbase + 1) & 0x7f);		clk_invalid = 1;	}#ifdef PROBE_BUSCLOCK	/*	 * Do the next twice for two reasons. First make sure we run from	 * cache. Second make sure synched on second update. (Pun intended!)	 */	for(i = 2;  i != 0; i--) {		int timeout, sec, cur, cnt;		cnt = get_count();		timeout = 1000000;		outb(clkbase, inb(clkbase) | 0x40);	/* stop update */		sec = inb(clkbase + 1) & 0x0f; 		outb(clkbase, inb(clkbase) & ~0x40);	/* start update */		do {			timeout--;			outb(clkbase, inb(clkbase) | 0x40);			cur = inb(clkbase + 1) & 0x0f; 			outb(clkbase, inb(clkbase) & ~0x40);		} while(timeout != 0 && cur == sec);		cnt = get_count() - cnt;		if(timeout == 0) {			clk_invalid = 1;			return;		/* Get out if clock is not running */		}	}	/*	 *  Calculate the external bus clock frequency.	 */	md_cpufreq = (cnt + 50000) / 100000;	md_cpufreq *= 400000;	if(md_cpufreq < 66000000) {		md_cpufreq = 66666667;	}	if(md_cpufreq > 100000000) {		md_cpufreq = 100000000;	}#endif	GETHID1(i);	i = (i >> 28) & 0x0f;	md_pipefreq = (md_cpufreq / 10) * pllratio[i];;}/* *   Returns the CPU pipelie clock frequency */inttgt_pipefreq(){	if(md_pipefreq == 0) {		_probe_frequencies();	}	return(md_pipefreq);}/* *   Returns the external clock frequency, usually the bus clock */inttgt_cpufreq(){	if(md_cpufreq == 0) {		_probe_frequencies();	}	return(md_cpufreq);}/* *  Returns the current time if a TOD clock is present or 0 *  This code is defunct after 2088... (out of bits) */#define FROMBCD(x)      (((x) >> 4) * 10 + ((x) & 0xf))#define TOBCD(x)        (((x) / 10 * 16) + ((x) % 10)) #define YEARDAYS(year)  ((((year) % 4) == 0 && \                         ((year % 100) != 0 || (year % 400) == 0)) ? 366 : 365)#define SECMIN  (60)            /* seconds per minute */#define SECHOUR (60*SECMIN)     /* seconds per hour */#define SECDAY  (24*SECHOUR)    /* seconds per day */#define SECYR   (365*SECDAY)    /* seconds per common year */static const short dayyr[12] =    { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };time_ttgt_gettime(){	struct tm tm;        int clkbase = M48T37_BASE + 8;	time_t t;	if(clk_invalid) {		tm.tm_sec = 0;		tm.tm_min = 0;		tm.tm_hour = 0;		tm.tm_wday = 0;		tm.tm_mday = 1;		tm.tm_mon = 1;		tm.tm_year = 0;	}	else {		outb(clkbase, inb(clkbase) | 0x40);		tm.tm_sec = FROMBCD(inb(clkbase + 1));		tm.tm_min = FROMBCD(inb(clkbase + 2));		tm.tm_hour = FROMBCD(inb(clkbase + 3));		tm.tm_wday = FROMBCD(inb(clkbase + 4));		tm.tm_mday = FROMBCD(inb(clkbase + 5));		tm.tm_mon = FROMBCD(inb(clkbase + 6)) - 1;		tm.tm_year = FROMBCD(inb(clkbase + 7));		outb(clkbase, inb(clkbase) & ~0x40);	}	tm.tm_isdst = tm.tm_gmtoff = 0;	if(tm.tm_year < 90) {		tm.tm_year += 100;	}	t = gmmktime(&tm);	if(clk_invalid) {		tgt_settime(t);	}        return(t);}/* *  Set the current time if a TOD clock is present */voidtgt_settime(time_t t){	struct tm *tm;        int clkbase = M48T37_BASE + 8;	tm = gmtime(&t);	/* Enable register writing */	outb(clkbase, inb(clkbase) | 0x80);        outb(clkbase + 7, TOBCD(tm->tm_year % 100));        outb(clkbase + 6, TOBCD(tm->tm_mon + 1));        outb(clkbase + 5, TOBCD(tm->tm_mday));        outb(clkbase + 4, TOBCD(tm->tm_wday));        outb(clkbase + 3, TOBCD(tm->tm_hour));        outb(clkbase + 2, TOBCD(tm->tm_min));        outb(clkbase + 1, TOBCD(tm->tm_sec));	/* Transfer new time to counters */	outb(clkbase, inb(clkbase) & ~0x80);	clk_invalid = 0;}/* *  Print out any target specific memory information */voidtgt_memprint(){}voidtgt_machprint(){	printf("BSP Copyright 2001-2002, SBS Technologies, Inc.\n");	printf("CPU PowerPC %s @", md_cpuname());} /* *  Return a suitable address for the client stack. *  Usually top of RAM memory. */register_ttgt_clienttos(){	return((memorysize & ~7) - 64);}/* *  Flash programming support code. *//* *  Table of flash devices on target. See pflash_tgt.h. */struct fl_map tgt_fl_map[] = {        TARGET_FLASH_DEVICES};voidtgt_flashinit(){}struct fl_map *tgt_flashmap(){	return(tgt_fl_map);}   voidtgt_flashwrite_disable(){	out32(CPC700_MEMCFGADDR, CPC700_FWEN);	out32(CPC700_MEMCFGDATA, in32(CPC700_MEMCFGDATA) & ~0x80000000);}inttgt_flashwrite_enable(){	out32(CPC700_MEMCFGADDR, CPC700_FWEN);	out32(CPC700_MEMCFGDATA, in32(CPC700_MEMCFGDATA) | 0x80000000);	outb(P7E_FBMISC, inb(P7E_FBMISC) | P7E_FB_ENAB);	return(1);}inttgt_flashsetpageno(page) 	int page;{	int regval;	if(page < 0 && page >= PFLASH_PAGED_FLASH) {		return(-1);	}	tgt_flashwrite_enable();	regval = inb(P7E_FBMISC) & ~P7E_FB_MASK;	regval |= page << P7E_FB_SHFT;	outb(P7E_FBMISC, regval);	tgt_flashwrite_disable();	return(0);}voidtgt_flashinfo(void *p, size_t *t){	struct fl_map *map;	map = fl_find_map(p);	if(map) {		*t = map->fl_map_size;	}	else {		*t = 0;	}}voidtgt_flashprogram(void *p, int size, void *s, int endian){	printf("Programming flash %p:%p into %p\n", s, size, p);	if(fl_erase_device(p, size, TRUE)) {		printf("Erase failed!\n");		return;	}	if(fl_program_device(p, s, size, TRUE)) {		printf("Programming failed!\n");	}	fl_verify_device(p, s, size, TRUE);}/* *  Network stuff. */voidtgt_netinit(){}inttgt_ethaddr(char *p){	bcopy((void *)&hwethadr, p, 6);	return(0);}voidtgt_netreset(){}/* *   --- NVRAM handling code --- *//* *  Special copy that does it bytewise, guaranteed! */static void bytecopy __P((char *, char *, size_t));staticvoid bytecopy(char *src, char *dst, size_t size){	if(src == NULL) {		*dst = '\0';	}	else if (dst >= src && dst < src + size) {		src += size;		dst += size;		while (size--) {			*--dst = *--src;		}	}	else while (size--) {		*dst++ = *src++;	}}/* *  Read in environment from NV-ram and set. */voidtgt_mapenv(int (*func) __P((char *, char *))){	char *ep;	char env[256];	/*	 *  Check integrity of the NVRAM env area. If not in order	 *  initialize it to empty.	 */	if(cksum((void *)NVRAM_FIRST_ENV, NVRAM_SIZE_ENV, 0) != 0) {		nvram_invalid = 1;	}	else {		ep = (char *)NVRAM_FIRST_ENV + 2;			while(*ep != 0) {			char *val = 0, *p = env;			while((*p++ = *ep++) != 0 && (ep < (char *)NVRAM_LAST_ENV)) {				if((*(p - 1) == '=') && (val == NULL)) {					*(p - 1) = '\0';					val = p;				}			}			if(ep < (char *)NVRAM_LAST_ENV) {				(*func)(env, val);			}			else {				nvram_invalid = 2;				break;			}		}		bytecopy((char *)NVRAM_VXWORKS, env, sizeof(env));		(*func)("vxWorks", env);	}	sprintf(env, "%d", memorysize / (1024 * 1024));	(*func)("memsize", env);	sprintf(env, "%d", md_pipefreq);	(*func)("cpuclock", env);	sprintf(env, "%d", md_cpufreq);	(*func)("busclock", env);	(*func)("systype", "power7e");}inttgt_unsetenv(char *name){	char *ep;	char *np;	char *sp;	if(nvram_invalid) {		return(0);	}	ep = (char *)NVRAM_FIRST_ENV + 2;	while((*ep != '\0') && (ep < (char *)NVRAM_LAST_ENV)) {		np = name;		sp = ep;		while((*ep == *np) && (*ep != '=') && (*np != '\0')) {			ep++;			np++;		}		if((*np == '\0') && ((*ep == '\0') || (*ep == '='))) {			while(*ep++);			while(ep <= (char *)NVRAM_LAST_ENV) {				*sp++ = *ep++;			}			cksum((void *)NVRAM_FIRST_ENV, NVRAM_SIZE_ENV, 1);			return(1);		}		else if(*ep != '\0') {			while(*ep++ != '\0');		}	}	return(0);}inttgt_setenv(char *name, char *value){	char *ep;	int envlen;	/* Calculate total env mem size requiered */	envlen = strlen(name);	if(envlen == 0) {		return(0);	}	if(value != NULL) {		envlen += strlen(value);	}	envlen += 2;	/* '=' + null byte */	if(envlen > 255) {		return(0);	/* Are you crazy!? */	}	/* If NVRAM is found to be uninitialized, reinit it. */	if(nvram_invalid) {		*(char *)(NVRAM_FIRST_ENV + 2) = '\0';		*(char *)(NVRAM_FIRST_ENV + 3) = '\0';		cksum((void *)NVRAM_FIRST_ENV, NVRAM_SIZE_ENV, 1);		nvram_invalid = 0;#if 0		bytecopy(NVRAM_VXWORKS_DEFAULT, (char *)NVRAM_VXWORKS,			 sizeof(NVRAM_VXWORKS_DEFAULT));#endif	}	if(strcmp("vxWorks", name) == 0) {		bytecopy(value, (char *)NVRAM_VXWORKS, envlen);		return(1);	}	/* Remove any current setting */	tgt_unsetenv(name);	/* Find end of evironment strings */	ep = (char *)NVRAM_FIRST_ENV + 2;	if(*ep != '\0') {		do {			while(*ep++ != '\0');		} while(*ep++ != '\0');		ep--;	}	if((NVRAM_LAST_ENV - (int)ep) < (envlen + 1)) {		return(0);	/* Bummer! */ 	}	/*	 *  Special case heaptop must always be first since it	 *  can change how memory allocation works.	 */	if(strcmp("heaptop", name) == 0) {		bytecopy((char *)NVRAM_FIRST_ENV + 2,			 (char *)NVRAM_FIRST_ENV + 2 + envlen,			 (int)ep - (NVRAM_FIRST_ENV + 1));		ep = (char *)NVRAM_FIRST_ENV + 2;		while(*name != '\0') {			*ep++ = *name++;		}		if(value != NULL) {			*ep++ = '=';			while((*ep++ = *value++) != '\0');		}		else {			*ep++ = '\0';		}	}	else {		while(*name != '\0') {			*ep++ = *name++;		}		if(value != NULL) {			*ep++ = '=';			while((*ep++ = *value++) != '\0');		}		else {			*ep++ = '\0';		}		*ep++ = '\0';	/* End of env strings */	}	cksum((void *)NVRAM_FIRST_ENV, NVRAM_SIZE_ENV, 1);		return(1);}/* *  Calculate checksum. If 'set' checksum is calculated and set. */#define __PUTW(a, d)				\	do {					\		u_int8_t *p = (u_int8_t *)a;	\		p[0] = d >> 8; p[1] = d; 	\	} while(0)#define __GETW(a)				\	((((u_int8_t *)p)[0] << 8) | ((u_int8_t*)p)[1])static intcksum(void *p, size_t s, int set){	u_int16_t *sp = p, sum = 0;	int sz = s / 2;	if(set) {		__PUTW(sp, 0);	/* Clear checksum */	}	while(sz--) {		sum += __GETW(sp);		sp++;	}	if(set) {		 __PUTW(p, -sum);	}	return(sum);}/* *  Simple display function to display a 4 char string or code. *  Called during startup to display progress on any feasible *  display before any serial port have been initialized. */voidtgt_display(char *msg, int x){	/* Have simple serial port driver */	tgt_putchar(msg[0]);	tgt_putchar(msg[1]);	tgt_putchar(msg[2]);	tgt_putchar(msg[3]);	tgt_putchar('\r');	tgt_putchar('\n');}voidclrhndlrs(){}inttgt_getmachtype(){	return(md_cputype());}voidtgt_reboot(){ 	while(1) {		int i;		outb(M48T37_BASE + 7, 0x81);		i = 200000;		while(i--);	}}voidtgt_devinit(){	/*	 * PCI device initialization	 */	_pci_businit(1);}/* *  Put all machine dependent initialization here. This call *  is done after console has been initialized so it's safe *  to output configuration and debug information with printf. */voidtgt_devconfig(){	/*	 * PCI device initialization	 */	_pci_devinit(1);	config_init();	configure();}/* *  Create stubs if network is not compiled in */#ifdef INETvoidtgt_netpoll(){	splx(splhigh());}#elsegsignal(jmp_buf jb, int	sig){	if(jb != NULL) {		longjmp(jb, 1);	}}netopen()	{ return -1;}netread()	{ return -1;}netwrite()	{ return -1;}netclose()	{ return -1;}netlseek()	{ return -1;}netioctl()	{ return -1;}void netpoll()	{}unsigned long__time(){	return(tgt_gettime));}#endif /*INET*/

⌨️ 快捷键说明

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