tgt_machdep.c

来自「国产CPU-龙芯(loongson)BIOS源代码」· C语言 代码 · 共 1,971 行 · 第 1/3 页

C
1,971
字号
	/* Non permanent vars. */	if(strcmp(EXPERT, name) == 0) {		return(1);	}        /* 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!? */        }	/* Use first defined flash device (we probably have only one) */#ifdef NVRAM_IN_FLASH        nvram = (char *)(tgt_flashmap())->fl_map_base;	/* Deal with an entire sector even if we only use part of it */        nvram += NVRAM_OFFS & ~(NVRAM_SECSIZE - 1);#endif        /* If NVRAM is found to be uninitialized, reinit it. */	if(nvram_invalid) {		nvramsecbuf = (char *)malloc(NVRAM_SECSIZE);		if(nvramsecbuf == 0) {			printf("Warning! Unable to malloc nvrambuffer!\n");			return(-1);		}#ifdef NVRAM_IN_FLASH		memcpy(nvramsecbuf, nvram, NVRAM_SECSIZE);#endif		nvrambuf = nvramsecbuf + (NVRAM_OFFS & (NVRAM_SECSIZE - 1));                memset(nvrambuf, -1, NVRAM_SIZE);                nvrambuf[2] = '\0';                nvrambuf[3] = '\0';                cksum((void *)nvrambuf, NVRAM_SIZE, 1);		printf("Warning! NVRAM checksum fail. Reset!\n");#ifdef NVRAM_IN_FLASH                if(fl_erase_device(nvram, NVRAM_SECSIZE, FALSE)) {			printf("Error! Nvram erase failed!\n");			free(nvramsecbuf);                        return(-1);                }                if(fl_program_device(nvram, nvramsecbuf, NVRAM_SECSIZE, FALSE)) {			printf("Error! Nvram init failed!\n");			free(nvramsecbuf);                        return(-1);                }#else		nvram_put(nvramsecbuf);#endif                nvram_invalid = 0;		free(nvramsecbuf);        }        /* Remove any current setting */        tgt_unsetenv(name);        /* Find end of evironment strings */	nvramsecbuf = (char *)malloc(NVRAM_SECSIZE);	if(nvramsecbuf == 0) {		printf("Warning! Unable to malloc nvrambuffer!\n");		return(-1);	}#ifndef NVRAM_IN_FLASH	nvram_get(nvramsecbuf);#else        memcpy(nvramsecbuf, nvram, NVRAM_SECSIZE);#endif	nvrambuf = nvramsecbuf + (NVRAM_OFFS & (NVRAM_SECSIZE - 1));	/* Etheraddr is special case to save space */	if (strcmp("ethaddr", name) == 0) {		char *s = value;		int i;		int32_t v;		for(i = 0; i < 6; i++) {			gethex(&v, s, 2);			hwethadr[i] = v;			s += 3;         /* Don't get to fancy here :-) */		} 	} else {		ep = nvrambuf+2;		if(*ep != '\0') {			do {				while(*ep++ != '\0');			} while(*ep++ != '\0');			ep--;		}		if(((int)ep + NVRAM_SIZE - (int)ep) < (envlen + 1)) {			free(nvramsecbuf);			return(0);      /* Bummer! */		}		/*		 *  Special case heaptop must always be first since it		 *  can change how memory allocation works.		 */		if(strcmp("heaptop", name) == 0) {			bcopy(nvrambuf+2, nvrambuf+2 + envlen,				 ep - nvrambuf+1);			ep = nvrambuf+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(nvrambuf, NVRAM_SIZE, 1);	bcopy(hwethadr, &nvramsecbuf[ETHER_OFFS], 6);#ifdef NVRAM_IN_FLASH        if(fl_erase_device(nvram, NVRAM_SECSIZE, FALSE)) {		printf("Error! Nvram erase failed!\n");		free(nvramsecbuf);                return(0);        }        if(fl_program_device(nvram, nvramsecbuf, NVRAM_SECSIZE, FALSE)) {		printf("Error! Nvram program failed!\n");		free(nvramsecbuf);                return(0);        }#else	nvram_put(nvramsecbuf);#endif	free(nvramsecbuf);        return(1);}/* *  Calculate checksum. If 'set' checksum is calculated and set. */static intcksum(void *p, size_t s, int set){	u_int16_t sum = 0;	u_int8_t *sp = p;	int sz = s / 2;	if(set) {		*sp = 0;	/* Clear checksum */		*(sp+1) = 0;	/* Clear checksum */	}	while(sz--) {		sum += (*sp++) << 8;		sum += *sp++;	}	if(set) {		sum = -sum;		*(u_int8_t *)p = sum >> 8;		*((u_int8_t *)p+1) = sum;	}	return(sum);}#ifndef NVRAM_IN_FLASH/* *  Read and write data into non volatile memory in clock chip. */voidnvram_get(char *buffer){#if 0	int i;	for(i = 0; i < 114; i++) {		linux_outb(i + RTC_NVRAM_BASE, RTC_INDEX_REG);	/* Address */		buffer[i] = linux_inb(RTC_DATA_REG);	}#endif}voidnvram_put(char *buffer){#if 0	int i;	for(i = 0; i < 114; i++) {		linux_outb(i+RTC_NVRAM_BASE, RTC_INDEX_REG);	/* Address */		linux_outb(buffer[i],RTC_DATA_REG);	}#endif}#endif/* *  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());}/* *  Create stubs if network is not compiled in */#ifdef INETvoidtgt_netpoll(){	splx(splhigh());}#elseextern void longjmp(label_t *, int);#if 0void gsignal(label_t *jb, int sig);voidgsignal(label_t *jb, int sig){	if(jb != NULL) {		longjmp(jb, 1);	}};#endifint	netopen (const char *, int);int	netread (int, void *, int);int	netwrite (int, const void *, int);long	netlseek (int, long, int);int	netioctl (int, int, void *);int	netclose (int);int netopen(const char *p, int i)	{ return -1;}int netread(int i, void *p, int j)	{ return -1;}int netwrite(int i, const void *p, int j)	{ return -1;}int netclose(int i)	{ return -1;}long int netlseek(int i, long j, int k)	{ return -1;}int netioctl(int j, int i, void *p)	{ return -1;}void tgt_netpoll()	{};#endif /*INET*/#define SPINSZ		0x800000#define DEFTESTS	7#define MOD_SZ		20#define BAILOUT		if (bail) goto skip_test;#define BAILR		if (bail) return;/* memspeed operations */#define MS_BCOPY	1#define MS_COPY		2#define MS_WRITE	3#define MS_READ		4struct map_struct {	unsigned long *start;	unsigned long *end;};struct map_struct map[] = {    {(unsigned long*)0x80100000,(unsigned long*)(0x84000000 - 0x100000)},   {(unsigned long*)0x0,(unsigned long*)0x0}};int segs=1;int bail;volatile unsigned long *p;unsigned long p1, p2;int test_ticks, nticks;unsigned long bad;int ecount = 0, errors = 0;void poll_errors(void);static void update_err_counts(void);static unsigned long my_roundup(unsigned long value, unsigned long mask){	return (value + mask) & ~mask;}/* * Print an individual error */void print_err( unsigned long *adr, unsigned long good, unsigned long bad, unsigned long xor) {	printf("adr=%x,good=%x,bad=%x,xor=%x\n",adr,good,bad,xor);}/* * Display data error message. Don't display duplicate errors. */void error(unsigned long *adr, unsigned long good, unsigned long bad){	unsigned long xor;	xor = good ^ bad;	update_err_counts();	print_err(adr, good, bad, xor);}/* * Display data error message from the block move test.  The actual failing * address is unknown so don't use this failure information to create * BadRAM patterns. */void mv_error(unsigned long *adr, unsigned long good, unsigned long bad){	unsigned long xor;	update_err_counts();	xor = good ^ bad;	print_err(adr, good, bad, xor);}/* * Display address error message. * Since this is strictly an address test, trying to create BadRAM * patterns does not make sense.  Just report the error. */void ad_err1(unsigned long *adr1, unsigned long *adr2, unsigned long good, unsigned long bad){	unsigned long xor;	update_err_counts();	xor = ((unsigned long)adr1) ^ ((unsigned long)adr2);	print_err(adr1, good, bad, xor);}/* * Display address error message. * Since this type of address error can also report data errors go * ahead and generate BadRAM patterns. */void ad_err2(unsigned long *adr, unsigned long bad){#if 0	int patnchg;	/* Process the address in the pattern administration */	patnchg=insertaddress ((unsigned long) adr);#endif	update_err_counts();	print_err(adr, (unsigned long)adr, bad, ((unsigned long)adr) ^ bad);}void print_hdr(void){	printf("Tst  Pass   Failing Address          Good       Bad     Err-Bits  Count Chan\n");	printf("---  ----  -----------------------  --------  --------  --------  ----- ----\n");}static void update_err_counts(void){	++(ecount);	errors++;}/* * Show progress by displaying elapsed time and update bar graphs */void do_tick(void){	printf(".");}/* * Memory address test, walking ones */void addr_tst1(void){	int i, j, k;	volatile unsigned long *pt;	volatile unsigned long *end;	unsigned long bad, mask, bank;	printf("address test 1..\n");	/* Test the global address bits */	for (p1=0, j=0; j<2; j++) {        	//hprint(LINE_PAT, COL_PAT, p1);		printf("\npat=%x\n",p1);		/* Set pattern in our lowest multiple of 0x20000 */		p = (unsigned long *)my_roundup((unsigned long)map[0].start, 0x1ffff);		*p = p1;			/* Now write pattern compliment */		p1 = ~p1;		end = map[segs-1].end;		for (i=0; i<1000; i++) {			mask = 4;			do {				pt = (unsigned long *)((unsigned long)p | mask);				if (pt == p) {					mask = mask << 1;					continue;				}				if (pt >= end) {					break;				}				*pt = p1;				if ((bad = *p) != ~p1) {					ad_err1((unsigned long *)p, (unsigned long *)mask,						bad, ~p1);					i = 1000;				}				mask = mask << 1;			} while(mask);		do_tick();		}		BAILR	}	/* Now check the address bits in each bank */	/* If we have more than 8mb of memory then the bank size must be */	/* bigger than 256k.  If so use 1mb for the bank size. */	if (map[segs-1].end - map[0].start > (0x800000 >> 12)) {		bank = 0x100000;	} else {		bank = 0x40000;	}	for (p1=0, k=0; k<2; k++) {        	//hprint(LINE_PAT, COL_PAT, p1);		printf("\npat=%x\n",p1);		for (j=0; j<segs; j++) {			p = map[j].start;			/* Force start address to be a multiple of 256k */			p = (unsigned long *)my_roundup((unsigned long)p, bank - 1);			end = map[j].end;			while (p < end) {				*p = p1;				p1 = ~p1;				for (i=0; i<200; i++) {					mask = 4;					do {						pt = (unsigned long *)						    ((unsigned long)p | mask);						if (pt == p) {							mask = mask << 1;							continue;						}						if (pt >= end) {							break;						}						*pt = p1;						if ((bad = *p) != ~p1) {							ad_err1((unsigned long *)p,							    (unsigned long *)mask,							    bad,~p1);							i = 200;						}						mask = mask << 1;					} while(mask);				}				if (p + bank > p) {					p += bank;				} else {					p = end;				}				p1 = ~p1;			}			do_tick();		}		BAILR		p1 = ~p1;	}}/* * Memory address test, own address */void addr_tst2(void){	int j, done;	volatile unsigned long *pe;	volatile unsigned long *end, *start;        //cprint(LINE_PAT, COL_PAT, "        ");	printf("addr test 2...\n");	/* Write each address with it's own address */	for (j=0; j<segs; j++) {		start = map[j].start;		end = map[j].end;		pe = (unsigned long *)start;		p = start;		done = 0;		do {			/* Check for overflow */			if (pe + SPINSZ > pe) {				pe += SPINSZ;			} else {				pe = end;			}			if (pe >= end) {				pe = end;				done++;			}			if (p == pe ) {				break;			} 			for (; p < pe; p++) {				*p = (unsigned long)p;			}			do_tick();			BAILR		} while (!done);	}	/* Each address should have its own address */	for (j=0; j<segs; j++) {		start = map[j].start;		end = map[j].end;		pe = (unsigned long *)start;		p = start;		done = 0;		do {			/* Check for overflow */			if (pe + SPINSZ > pe) {				pe += SPINSZ;			} else {				pe = end;			}			if (pe >= end) {				pe = end;				done++;			}			if (p == pe ) {				break;			} 			for (; p < pe; p++) { 				if((bad = *p) != (unsigned long)p) { 					ad_err2((unsigned long*)p, bad); 				} 			}			do_tick();			BAILR		} while (!done);	}}/* * Test all of memory using a "moving inversions" algorithm using the * pattern in p1 and it's complement in p2. */void movinv1(int iter, unsigned long p1, unsigned long p2){	int i, j, done;	volatile unsigned long *pe;	volatile unsigned long len;	volatile unsigned long *start,*end;	/* Display the current pattern */        //hprint(LINE_PAT, COL_PAT, p1);	printf("movinv test with p1=%x,p2=%x...\n",p1,p2);	/* Initialize memory with the initial pattern.  */	for (j=0; j<segs; j++) {		start = map[j].start;		end = map[j].end;		pe = start;		p = start;		done = 0;		do {			/* Check for overflow */			if (pe + SPINSZ > pe) {				pe += SPINSZ;			} else {				pe = end;			}			if (pe >= end) {				pe = end;				done++;			}			len = pe - p;			if (p == pe ) {				break;			}			for (; p < pe; p++) {				*p = p1;			}			do_tick();			BAILR		} while (!done);	}	/* Do moving inversions test. Check for initial pattern and then	 * write the complement for each memory location. Test from bottom	 * up and then from the top down.  */	for (i=0; i<iter; i++) {		for (j=0; j<segs; j++) {			start = map[j].start;			end = map[j].end;			pe = start;			p = start;			done = 0;			do {				/* Check for overflow */				if (pe + SPINSZ > pe) {					pe += SPINSZ;				} else {					pe = end;				}				if (pe >= end) {					pe = end;					done++;				}				if (p == pe ) {					break;				}				for (; p < pe; p++) {					if ((bad=*p) != p1) {						error((unsigned long*)p, p1, bad);

⌨️ 快捷键说明

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