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 + -
显示快捷键?