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

📄 nvram.c

📁 mips架构的bootloader,99左右的版本 但源代码现在没人更新了
💻 C
字号:
/************************************************************* * File: lib/nvram.c * Purpose: Part of C runtime library * Author: Phil Bunce (pjb@carmel.com) * Revision History: *	970304	Start of revision history *	970311	Added flush_cache(DCACHE) for 4010 copy-back *	970605	Added writeFlash *	970620	Cygnus requires Uchar in flash29. *	970910	Added support for Am29F080. *	971124	Don't create msg for famcode=0000. *	971125	Added code to writeFlash for 4011 copy from boot eprom *	980114	Added delay to start of nvType for GHS+4011. *	980120	Replaced outb() macro with a function. Fixes prob w *		nvType check on 4011. Removed delay. *	980324	Fixed problem with outb. It wasn't doing the right thing. *	980508	Added needcpy. *	980508	Flush D before I in nvCheck. *	980509	Discovered that for needcpy=1 outb MUST be a macro. *	980509	The new outb macro works on 4011 but fails on 4101. *	980510	Reverted to old outb macro until real fix is found. *	980602	Delay shrc execution until after the powerup banner. *		Do this by setting shrc_needed. *	980715	Modified do_shrc and shrc to support 2 separate init *		blocks. Before p2 is executed before the banner. After *		p2 is executed after the banner. Only commands that *		were specified in the "set nvram" command are located *		after the p2. *//*************************************************************  * Performance data: *	3 secs to erase one sector *	128 secs/MB for writes */#include <stdio.h>#include <mips.h>#include <termio.h>#include <mon.h>#define inb(x)	(*(volatile Uchar *)(x))#if 0#define outb(a,v)   *((Uchar *)(a))=((Uchar)(v))#else/**************************************************************  outb(a,v)   *	store byte with write buffer flush.*	For 4011 you MUST use Kseg1 addresses for tmp1 and tmp2.*	980324 Added & for wbflushtmpX and volatile for wbftX.*/#define outb(a,v)   					\{							\volatile int *wbft1,*wbft2;				\							\*((Uchar *)(a))=((Uchar)(v));				\wbft1 = (int *)(((Ulong)&wbflushtmp1)|K1BASE);		\wbft2 = (int *)(((Ulong)&wbflushtmp2)|K1BASE);		\*wbft1 = 0;						\*wbft2 = *wbft1;					\}#endifint nvType(),nvType_end();int flash28(),flash28end();int flash29(),flash29end();int xl28(),xl28end();NvType nvTypes[] = {	{0x01a2,"Am28F010",0,      128*1024,flash28,flash28end}, 	{0x01a7,"Am28F010",0,	   128*1024,flash28,flash28end},	{0x89b4,"i28F010", 0,	   128*1024,flash28,flash28end},	{0x89bd,"i28F020", 0,	   256*1024,flash28,flash28end},	{0x0120,"Am29F010",16*1024,128*1024,flash29,flash29end},	{0x01a4,"Am29F040",64*1024,512*1024,flash29,flash29end},	{0xc0a4,"Am29F040",64*1024,512*1024,flash29,flash29end},	{0x01d5,"Am29F080",64*1024,1024*1024,flash29,flash29end},	{0x1f5b,"AT29F040",64*1024,512*1024,flash29,flash29end}, /* atmel */	{0x5010,"XL28C64", 1,	   1024,xl28,xl28end}, 	{0}};NvInfo nvInfo;#define SPC_BITMSK (3<<21)#define SPC_8BIT   (1<<21)#define SPC_16BIT  (2<<21)#define SPC_32BIT  (3<<21)int machtype;volatile int wbflushtmp1;volatile int wbflushtmp2;int shrc_needed;#ifdef TEST/**************************************************************  main()*/main(argc,argv)int argc;char *argv[];{int n,i,j,c;char nvtype[40];machtype = getmachtype();if (!nvCheck(nvtype)) printf("nvCheck FAILED\n");;printf("nvram: %s\n",nvtype);printf("reading: ");for (i=0;;i++) {	c = nvRead(i);	if (c == 0 || c == 0xff) break;	putchar(c);	}putchar('\n');if (argc == 1) return;for (j=1,i=0;j<argc;j++) {	if (argv[j][0] == '-') {		if (argv[j][1] == 'c') nvClear();		else if (argv[j][1] == 'v') {			j++;			for (i=0;j<argc;j++) {				for (p=argv[j];*p;p++) nvWrite(i++,*p);				nvWrite(i++,' ');				}			}		else {			printf("%s: bad option\n",argv[j][1]);			printf("usage: [-c] [-v msg]\n");			exit(1);			}		}	else {		printf("%s: bad argument\n",argv[j]);		printf("usage: [-c] [-v msg]\n");		exit(1);		}	}printf("reading: ");for (i=0;;i++) {	c = nvRead(i);	if (c == 0 || c == 0xff) break;	putchar(c);	}putchar('\n');}#endif/**************************************************************  int nvCheck(char *msg)*/nvCheck(msg)char *msg;{Ulong r;int len,i,famcode;Func *f;int needcpy;*msg = 0;if (nvInfo.nvbase) return(1);#if 0/* check to see if I am executing out of flash *//* do this by checking if I am in the same 8MB as nvInfo.start *//* if so, I must copy some routines to RAM before executing them */if ((((Ulong)nvCheck)&~(0x800000-1)) == nvInfo.start&~(0x800000-1)) needcpy=1;else needcpy = 0;#elseneedcpy=1;#endif/* first, find out what nvType we have */if (needcpy) {	len = ((Ulong)nvType_end)-((Ulong)nvType);	f = (Func *)malloc(len + jalBytes(nvType,len/4));	if (!f) {		strcpy(msg,"malloc failure 1");		return(0);		}	codecpy(f,nvType,len/4);	flush_cache(DCACHE);	flush_cache(ICACHE);	famcode = (* f)();	free(f);	}else famcode = nvType();/* look up the famcode in the nvTypes table */for (i=0;nvTypes[i].driver;i++) {	if (nvTypes[i].famcode == famcode) break;	}if (!nvTypes[i].driver) { /* famcode not found */	nvInfo.nvbase = 0;	if (msg && famcode != 0) sprintf(msg,"%04x: Bad flashcode",famcode);	return(0);	}nvInfo.name = nvTypes[i].name;/* now, install the correct driver */if (needcpy) {	len = ((Ulong)nvTypes[i].edriver)-((Ulong)nvTypes[i].driver);	f = (Func *)malloc(len + jalBytes(nvTypes[i].driver,len/4));	if (!f) {		strcpy(msg,"malloc failure 2");		return(0);		}	codecpy(f,nvTypes[i].driver,len/4);	flush_cache(DCACHE);	flush_cache(ICACHE);	nvInfo.driver = f;	}else nvInfo.driver = nvTypes[i].driver;nvInfo.size = nvTypes[i].size;nvInfo.type = &nvTypes[i];/* return if this device doesn't support sector erase */if (!nvTypes[i].se) {	nvInfo.nvbase = 0;	if (msg) strcpy(msg,"Function not supported");	return(0);	}/* calculate the correct value for nvbase */if (nvInfo.nvbase == 0) {	len = nvInfo.size*nvInfo.width;	len -= nvTypes[i].se*nvInfo.width;#if 0 /* we aught to check if there's enough room */	if (len <= PMONsize) {		nvInfo.nvbase = 0;		if (msg) strcpy(msg,"Insufficient space");		return(0);		}#endif	nvInfo.nvbase = nvInfo.start + len;	len -= nvTypes[i].se*nvInfo.width;	nvInfo.dvrsa = nvInfo.start + len;	}/*printf("famcode=%04x ",famcode); /*  */if (msg) strcpy(msg,nvInfo.name);return(1);}/**************************************************************  nvWrite(adr,val)*/nvWrite(adr,val)Ulong adr;int val;{if (!nvInfo.nvbase) return;if (adr == 0) nvClear();(* nvInfo.driver)(NV_WRITE,nvInfo.nvbase+(adr*nvInfo.gap),val);}/**************************************************************  nvRead(adr)*/nvRead(adr)Ulong adr;{if (!nvInfo.nvbase) return(0);return inb(nvInfo.nvbase+(adr*nvInfo.gap));}/**************************************************************  nvClear()*/nvClear(){int i;if (!nvInfo.nvbase) return;if (nvInfo.start == nvInfo.nvbase) (* nvInfo.driver)(NV_ERASE,nvInfo.start);else {	for (i=0;i<nvInfo.width;i++) {		(* nvInfo.driver)(NV_SERASE,nvInfo.nvbase+i);		}	}}/**************************************************************  nvType()*	determine family code*	what we do know at start:*		start address of device*		gap*		width*/nvType(){Ulong adrA,adrB,adr0,adr1;Ulong msk;int sh,b1,b2,h0,h1;sh = nvInfo.width/2;adrA = (nvInfo.start|(0x5555<<sh));adrB = (nvInfo.start|(0x2aaa<<sh));adr0 = (nvInfo.start|(0x0000<<sh));adr1 = (nvInfo.start|(0x0001<<sh));b1 = inb(adr0);b2 = inb(adr1);h0 =  (b1<<8)|b2; /* read the existing value */outb(adrA,0xaa); outb(adrB,0x55); outb(adrA,0x90); b1 = inb(adr0);b2 = inb(adr1);outb(adrA,0xaa); outb(adrB,0x55); outb(adrA,0xf0); h1 =  (b1<<8)|b2; /* read the famcode */if (h0 == h1) return(0); /* must be eprom */return(h1);}nvType_end() {}/**************************************************************  flash28(op,adr,val) */flash28(op,adr,val) int op,val;Ulong adr;{Uchar pvd;Ulong X,cs;int plscnt,dev,sh,i;		 printf("flash28: op=%d adr=%08x val=%02x\n",op,adr,val&0xff);switch (op) {	case NV_WRITE : 		printf("flash28w: NOT TESTED\n");		cs = nvInfo.nvbase&~3;		sh = nvInfo.width/2;		dev = adr&((1<<sh)-1);		X = cs|dev; /* any address within the device */		printf("nvbase=%08x X=%08x\n",nvInfo.nvbase,X);		for (plscnt=0;plscnt<25;plscnt++) {			outb(X,0x40); /* prog */			outb(adr,val);			for (i=500;i>0;i++) wbflushtmp1 = 0; /* 10us delay */			outb(X,0xc0); /* prog verify */			for (i=300;i>0;i++) wbflushtmp1 = 0; /* 6us delay */			pvd = inb(X); 			if (val == pvd) break;			}		printf("pvd=%02x plscnt=%d\n",pvd,plscnt);		/* outb(X,0xff); outb(X,0xff); outb(X,0x00); /* reset-rd */		if (plscnt >= 25) return(0);		return(1);	case NV_ERASE :		printf("flash28e: NOT IMPLEMENTED\n");		break;	case NV_SERASE :		printf("flash28se: NOT supported by device\n");		break;	}}flash28end() {}#define P29MAX	10 /* max polling count for 29F devices */int diagcnt;/**************************************************************  flash29(op,adr,val) */flash29(op,adr,val) int op;Ulong adr;Uchar val;{Ulong adrA,adrB,adr0,adr1;Uchar epd;int sh,cnt,i;switch (op) {	case NV_WRITE : 		sh = nvInfo.width/2;		adrA = ((adr&~(0x1ffff<<sh))|(0x5555<<sh));		adrB = ((adr&~(0x1ffff<<sh))|(0x2aaa<<sh));#if 0		printf("flash29w: adr=%08x val=%02x adrA=%08x adrB=%08x\n",			adr,val,adrA,adrB);#endif		outb(adrA,0xaa); outb(adrB,0x55); outb(adrA,0xa0); 		outb(adr,val);		for (i=0;i<3000;i++) wbflushtmp1 = 0; /* min 100us delay */		for (cnt=0;;cnt++) {			epd = inb(adr);			if ((epd&0x80) == (val&0x80) && epd == val) break; 			if (epd&(1<<5)) break;			}#if 0		if (epd != val) printf("flash29w: ## TIMEOUT\n");#endif		if (epd != val) return(0);		return(1);		break;	case NV_SERASE : 		sh = nvInfo.width/2;		adrA = ((adr&~(0x1ffff<<sh))|(0x5555<<sh));		adrB = ((adr&~(0x1ffff<<sh))|(0x2aaa<<sh));#if 0		printf("flash29se: adr=%08x adrA=%08x adrB=%08x\n",			adr,adrA,adrB);#endif		/* unlock, setup */		outb(adrA,0xaa); outb(adrB,0x55); outb(adrA,0x80); 		/* unlock, sectEra */		outb(adrA,0xaa); outb(adrB,0x55); outb(adr,0x30); 		for (i=0;i<3000;i++) wbflushtmp1 = 0; /* min 100us delay */		val = 0xff;		for (cnt=0;cnt<5000000;cnt++) { /* cnt=1.3M is normal */			epd = inb(adr);			if ((epd&0x80) == (val&0x80) && epd == val) break; 			if (epd&(1<<5)) break;			}#if 0		if (epd != val) printf("flash29se: ## TIMEOUT\n");		printf("flash29se: epd=%02x cnt=%d\n",epd,cnt);#endif		if (epd != val) return(0);		return(1);		break;	case NV_ERASE :		printf("flash29e: NOT IMPLEMENTED\n");		break;	default: printf("flash29: %d: bad opcode\n",op);	}}flash29end() {}#define XL28_TIMEOUT 100000/**************************************************************  xl28(op,adr,val) */xl28(op,adr,val) int op,val;Ulong adr;{int i,n;Ulong a;switch (op) {	case NV_WRITE :		outb(adr,val);		for (i=0;i<XL28_TIMEOUT && inb(adr) != val;i++) wbflushtmp1=0;		if (i >= XL28_TIMEOUT) return(0);		break;	case NV_ERASE :	case NV_SERASE :		/* clear nvram */		val = 0xff;		for (n=0;n<nvInfo.size;n++) {			if (nvRead(n) != val) {				a = nvInfo.nvbase+(n*nvInfo.gap);				outb(a,val);				for (i=0;i<XL28_TIMEOUT && inb(adr) != val;i++) 					wbflushtmp1=0;				if (i >= XL28_TIMEOUT) return(0);				}			}		break;	}}xl28end() {}/**************************************************************  do_shrc()*/do_shrc(){int c,n;char ch,buf[80];c = 'n';ioctl(STDIN,FIONREAD,&n);if (n != 0) {	for (;;) {		ioctl(STDIN,FIONREAD,&n);		if (n == 0) break;		read(STDIN,&ch,1);		}	for (;;) {		printf("Skip NVRAM read? (y/n)? >");		gets(buf);		c = *buf;		if (c == 'n' || c == 'y') break;		if (c == 'N' || c == 'Y') break;		}	}if (c == 'Y' || c == 'y') return;shrc(0);shrc_needed = 1; }/**************************************************************  shrc(n)*	n=0 do part1*	n=1 do part2*/shrc(n)int n;{int c;char buf[LINESZ];unsigned long adr;adr = 0;for (;;) {	c = getln(&adr,buf);	if (c == 0) break;	if (strequ(buf,"p2")) {		if (n == 0) break;		if (n == 1) n++;		}	else if (n == 2 || n == 0) do_cmd(buf);	}}/**************************************************************  getln(adr,p)*/getln(adr,p)unsigned long *adr;unsigned char *p;{unsigned int c = 0;long addr;addr = *adr;for (;;) {	c = nvRead(addr);	if (c == 0xff) c = 0;	if (c == 0) break;	addr++;	if (c == '\n') break;	*p++ = c;	}*adr = addr;*p = 0;return(c);}/**************************************************************  writeFlash(adr,val)*	This is used by self-updating flashes (xflash.c)*/writeFlash(adr,val)Ulong adr;Uchar val;{int se,width;Ulong msk;char nvtype[20];if (!nvInfo.type) return(0);se = nvInfo.type->se;width = nvInfo.width;msk = ((se*width)-1) & ~(width-1);if ((adr&msk) == 0) (* nvInfo.driver)(NV_SERASE,adr);(* nvInfo.driver)(NV_WRITE,adr,val);return(0);}#if 0/**************************************************************/printNvInfo(){printf("name=%s start=%08x width=%d size=0x%x gap=%d nvbase=%08x driver=%08x\n",	nvInfo.name, nvInfo.start, nvInfo.width, nvInfo.size, nvInfo.gap,	nvInfo.nvbase,nvInfo.driver);if (nvInfo.type)	printf("famcode=%04x name=%s se=0x%x size=0x%x driver=%08x\n", 		nvInfo.type->famcode, nvInfo.type->name, nvInfo.type->se, 		nvInfo.type->size,nvInfo.type->driver);}#endif

⌨️ 快捷键说明

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